Ejemplo n.º 1
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({'MOZ_CRASHREPORTER': '1',
                    'MOZ_CRASHREPORTER_NO_REPORT': '1'})
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args)
        self.runner.start()
Ejemplo n.º 2
0
    def start(self):
        profile_args = {"preferences": self.required_prefs}
        if not self.profile_path:
            profile_args["restore"] = False
            profile = Profile(**profile_args)
        else:
            profile_args["path_from"] = self.profile_path
            profile = Profile.clone(**profile_args)

        if self.gecko_log is None:
            self.gecko_log = 'gecko.log'
        elif os.path.isdir(self.gecko_log):
            fname = "gecko-%d.log" % time.time()
            self.gecko_log = os.path.join(self.gecko_log, fname)

        self.gecko_log = os.path.realpath(self.gecko_log)
        if os.access(self.gecko_log, os.F_OK):
            os.remove(self.gecko_log)

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args={
                'processOutputLine': [NullOutput()],
                'logfile': self.gecko_log})
        self.runner.start()
Ejemplo n.º 3
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args)
        self.runner.start()
Ejemplo n.º 4
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if not self.profile_path:
            profile_args["restore"] = False
            profile = Profile(**profile_args)
        else:
            profile_args["path_from"] = self.profile_path
            profile = Profile.clone(**profile_args)

        if self.gecko_log is None:
            self.gecko_log = 'gecko.log'
        elif os.path.isdir(self.gecko_log):
            fname = "gecko-%d.log" % time.time()
            self.gecko_log = os.path.join(self.gecko_log, fname)

        self.gecko_log = os.path.realpath(self.gecko_log)
        if os.access(self.gecko_log, os.F_OK):
            if platform.system() is 'Windows':
                # NOTE: windows has a weird filesystem where it happily 'closes'
                # the file, but complains if you try to delete it. You get a
                # 'file still in use' error. Sometimes you can wait a bit and
                # a retry will succeed.
                # If all retries fail, we'll just continue without removing
                # the file. In this case, if we are restarting the instance,
                # then the new logs just get appended to the old file.
                tries = 0
                while tries < 10:
                    try:
                        os.remove(self.gecko_log)
                        break
                    except WindowsError as e:
                        if e.errno == errno.EACCES:
                            tries += 1
                            time.sleep(0.5)
                        else:
                            raise e
            else:
                os.remove(self.gecko_log)

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args={
                'processOutputLine': [NullOutput()],
                'logfile': self.gecko_log})
        self.runner.start()
Ejemplo n.º 5
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"][
            "marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel":
                "jsdebugger",
                "devtools.debugger.remote-enabled":
                True,
                "devtools.chrome.enabled":
                True,
                "devtools.debugger.prompt-connection":
                False,
                "marionette.debugging.clicktostart":
                True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({
            'MOZ_CRASHREPORTER': '1',
            'MOZ_CRASHREPORTER_NO_REPORT': '1',
        })
        self.runner = Runner(binary=self.bin,
                             profile=self.profile,
                             cmdargs=['-no-remote', '-marionette'] +
                             self.app_args,
                             env=env,
                             symbols_path=self.symbols_path,
                             process_args=process_args)
        self.runner.start()
Ejemplo n.º 6
0
    def _update_profile(self, profile=None, profile_name=None):
        """Check if the profile has to be created, or replaced.

        :param profile: A Profile instance to be used.
        :param name: Profile name to be used in the path.
        """
        if self.runner and self.runner.is_running():
            raise errors.MarionetteException(
                "The current profile can only be updated "
                "when the instance is not running"
            )

        if isinstance(profile, Profile):
            # Only replace the profile if it is not the current one
            if hasattr(self, "_profile") and profile is self._profile:
                return

        else:
            profile_args = self.profile_args
            profile_path = profile

            # If a path to a profile is given then clone it
            if isinstance(profile_path, six.string_types):
                profile_args["path_from"] = profile_path
                profile_args["path_to"] = tempfile.mkdtemp(
                    suffix=u".{}".format(
                        profile_name or os.path.basename(profile_path)
                    ),
                    dir=self.workspace,
                )
                # The target must not exist yet
                os.rmdir(profile_args["path_to"])

                profile = Profile.clone(**profile_args)

            # Otherwise create a new profile
            else:
                profile_args["profile"] = tempfile.mkdtemp(
                    suffix=u".{}".format(profile_name or "mozrunner"),
                    dir=self.workspace,
                )
                profile = Profile(**profile_args)
                profile.create_new = True

        if isinstance(self.profile, Profile):
            self.profile.cleanup()

        self._profile = profile
Ejemplo n.º 7
0
 def test_with_profile_should_cleanup_even_on_exception(self):
     with self.assertRaises(ZeroDivisionError):
         with Profile() as profile:
             self.assertTrue(os.path.exists(profile.profile))
             1 / 0  # will raise ZeroDivisionError
     # profile is cleaned
     self.assertFalse(os.path.exists(profile.profile))
Ejemplo n.º 8
0
    def start_runner(self, binary, options):
        profile = Profile(profile=options.get('profile'))
        cmdargs = options.get('argv', [])

        if 'screen' in options and \
           'width' in options['screen']  and \
           'height' in options['screen']:
            screen = '--screen=%sx%s' % (options['screen']['width'], \
                                         options['screen']['height'])

            if 'dpi' in options['screen']:
                screen = '%s@%s' % (screen, options['screen']['dpi'])
            cmdargs.append(screen)

        if options.get('noRemote', True):
            cmdargs.append('-no-remote')

        if options.get('url'):
            cmdargs.append(options['url'])

        if options.get('chrome'):
            cmdargs.extend(['-chrome', options['chrome']])

        if options.get('startDebugger'):
            cmdargs.extend(
                ['-start-debugger-server', options['startDebugger']])

        self.runner = B2GDesktopRunner(binary,
                                       cmdargs=cmdargs,
                                       profile=profile,
                                       **self.common_runner_args)
        self.runner.start()
Ejemplo n.º 9
0
    def start_runner(self, data):
        binary = os.path.join(data.get('target'), 'b2g-bin')
        options = data.get('options', {})

        profile = Profile(profile=options.get('profile'))
        cmdargs = options.get('argv', [])

        if options.get('screen') and \
           hasattr(options.screen, 'width') and \
           hasattr(options.screen, 'height'):
            screen = '--screen=%sx%s' % (options.screen.width,
                                         options.screen.height)
            if hasattr(options.screen, 'dpi'):
                screen = '%s@%s' % (screen, options.screen.dpi)
            cmdargs.append(screen)

        if options.get('noRemote', True):
            cmdargs.append('-no-remote')

        if options.get('url'):
            cmdargs.append(options['url'])

        if options.get('chrome'):
            cmdargs.extend(['-chrome', options['chrome']])

        if options.get('startDebugger'):
            cmdargs.extend(
                ['-start-debugger-server', options['startDebugger']])

        self.runner = B2GDesktopRunner(binary,
                                       cmdargs=cmdargs,
                                       profile=profile,
                                       **self.common_runner_args)
        self.runner.start()
Ejemplo n.º 10
0
    def install_profile(self, profile=None, root=True):
        if not profile:
            profile = Profile()

        profile_path_parent = os.path.split(self.profile_path)[0]
        success = False
        for attempt in range(1, self.options.phone_retry_limit+1):
            try:
                self.loggerdeco.debug('Attempt %d installing profile', attempt)
                if self.dm.exists(self.profile_path, root=root):
                    # If the profile already exists, chmod it to make sure
                    # we have permission to delete it.
                    self.dm.chmod(self.profile_path, recursive=True, root=root)
                    self.dm.rm(self.profile_path, recursive=True,
                               force=True, root=root)
                self.dm.chmod(profile_path_parent, root=root)
                self.dm.mkdir(self.profile_path, root=root)
                self.dm.chmod(self.profile_path, root=root)
                self.dm.push(profile.profile, self.profile_path)
                self.dm.chmod(self.profile_path, recursive=True, root=root)
                success = True
                break
            except ADBError:
                self.loggerdeco.exception('Attempt %d Exception installing '
                                          'profile to %s' % (
                                              attempt, self.profile_path))
                sleep(self.options.phone_retry_wait)

        if not success:
            self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                             'Failure installing profile to %s' % self.profile_path,
                             TreeherderStatus.TESTFAILED)

        return success
Ejemplo n.º 11
0
def tps_profile(pytestconfig, tps_addon, tps_config, tps_log, fxa_urls):
    preferences = {
        'browser.onboarding.enabled': False,
        'browser.startup.homepage_override.mstone': 'ignore',
        'browser.startup.page': 0,
        'datareporting.policy.dataSubmissionEnabled': False,
        # 'devtools.chrome.enabled': True,
        # 'devtools.debugger.remote-enabled': True,
        'extensions.autoDisableScopes': 10,
        'extensions.legacy.enabled': True,
        'identity.fxaccounts.autoconfig.uri': fxa_urls['content'],
        'testing.tps.skipPingValidation': True,
        'services.sync.log.appender.console': 'Trace',
        'services.sync.log.appender.dump': 'Trace',
        'services.sync.log.appender.file.level': 'Trace',
        'services.sync.log.appender.file.logOnSuccess': True,
        'services.sync.log.logger': 'Trace',
        'services.sync.log.logger.engine': 'Trace',
        'tps.config': json.dumps(tps_config),
        'tps.logfile': tps_log,
        'tps.seconds_since_epoch': int(time.time()),
        'xpinstall.signatures.required': False
    }
    profile = Profile(addons=[tps_addon], preferences=preferences)
    pytestconfig._profile = profile.profile
    yield profile
Ejemplo n.º 12
0
    def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
        """Runs the given FirefoxRunner with the given Profile, waits
           for completion, then returns the process exit code
        """
        if profile is None:
            profile = Profile()
        self.profile = profile

        if self.binary is None and self.url:
            self.binary = self.download_build()

        if self.runner is None:
            self.runner = FirefoxRunner(self.profile, binary=self.binary)

        self.runner.profile = self.profile

        if env is not None:
            self.runner.env.update(env)

        if args is not None:
            self.runner.cmdargs = copy.copy(args)

        self.runner.start()
        returncode = self.runner.wait(timeout)

        return returncode
Ejemplo n.º 13
0
def test_with_profile_should_cleanup_even_on_exception():
    with pytest.raises(ZeroDivisionError):
        with Profile() as profile:
            assert os.path.exists(profile.profile)
            1 / 0  # will raise ZeroDivisionError

    # profile is cleaned
    assert not os.path.exists(profile.profile)
Ejemplo n.º 14
0
 def build_profile(self):
     test_root = self.dm.deviceRoot
     self.remote_profile = posixpath.join(test_root, 'gv-profile')
     self.dm.mkDirs(posixpath.join(self.remote_profile, "x"))
     profile = Profile()
     self.dm.pushDir(profile.profile, self.remote_profile)
     self.log.debug("profile %s -> %s" %
                    (str(profile.profile), str(self.remote_profile)))
 def build_profile(self):
     test_root = self.device.test_root
     self.remote_profile = posixpath.join(test_root, 'gv-profile')
     self.device.mkdir(self.remote_profile, parents=True)
     profile = Profile()
     self.device.push(profile.profile, self.remote_profile)
     self.log.debug("profile %s -> %s" %
                    (str(profile.profile), str(self.remote_profile)))
Ejemplo n.º 16
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args)
        self.runner.start()
Ejemplo n.º 17
0
    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"][
            "marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel":
                "jsdebugger",
                "devtools.debugger.remote-enabled":
                True,
                "devtools.chrome.enabled":
                True,
                "devtools.debugger.prompt-connection":
                False,
                "marionette.debugging.clicktostart":
                True,
            })
        if self.addons:
            profile_args["addons"] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args["profile"] = tempfile.mkdtemp(
                        suffix=".mozrunner-{:.0f}".format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = "{}-{:.0f}".format(
                    os.path.basename(self.profile_path), time.time())
                if self.workspace:
                    profile_args["path_to"] = os.path.join(
                        self.workspace, profile_name)

                # nekonbu72 +
                profile_args["ignore"] = lambda src, names: "parent.lock"

                self.profile = Profile.clone(**profile_args)
Ejemplo n.º 18
0
    def start_runner(self, binary, options):
        port = options.get('port')
        profile = Profile(profile=options.get('profile'))

        self.runner.device.setup_port_forwarding(local_port=port, remote_port=port)

        self.runner.profile = profile
        self.runner.start()
        if not self.runner.device.wait_for_port(port):
            raise Exception("Wait for port timed out")
Ejemplo n.º 19
0
    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" % (options.webServer, options.httpPort),
            "OOP": "true" if self.out_of_process else "false"
        }
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {
                "remote": options.webServer
            }
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest
Ejemplo n.º 20
0
    def _update_profile(self, profile=None, profile_name=None):
        """Check if the profile has to be created, or replaced

        :param profile: A Profile instance to be used.
        :param name: Profile name to be used in the path.
        """
        if self.runner and self.runner.is_running():
            raise errors.MarionetteException("The current profile can only be updated "
                                             "when the instance is not running")

        if isinstance(profile, Profile):
            # Only replace the profile if it is not the current one
            if hasattr(self, "_profile") and profile is self._profile:
                return

        else:
            profile_args = self.profile_args
            profile_path = profile

            # If a path to a profile is given then clone it
            if isinstance(profile_path, basestring):
                profile_args["path_from"] = profile_path
                profile_args["path_to"] = tempfile.mkdtemp(
                    suffix=".{}".format(profile_name or os.path.basename(profile_path)),
                    dir=self.workspace)
                # The target must not exist yet
                os.rmdir(profile_args["path_to"])

                profile = Profile.clone(**profile_args)

            # Otherwise create a new profile
            else:
                profile_args["profile"] = tempfile.mkdtemp(
                    suffix=".{}".format(profile_name or "mozrunner"),
                    dir=self.workspace)
                profile = Profile(**profile_args)
                profile.create_new = True

        if isinstance(self.profile, Profile):
            self.profile.cleanup()

        self._profile = profile
Ejemplo n.º 21
0
    def build_profile(self):
        """
           Create a local profile with test prefs and proxy definitions and
           push it to the remote device.
        """

        self.profile = Profile(locations=self.locations, proxy=self.proxy(self.options))
        self.options.profilePath = self.profile.profile

        # Set preferences
        self.merge_base_profiles(self.options, 'geckoview-junit')
        prefs = parse_preferences(self.options.extra_prefs)
        self.profile.set_preferences(prefs)

        if self.fillCertificateDB(self.options):
            self.log.error("Certificate integration failed")

        self.device.push(self.profile.profile, self.remote_profile)
        self.log.debug("profile %s -> %s" %
                       (str(self.profile.profile), str(self.remote_profile)))
Ejemplo n.º 22
0
def create_mozprofile(profile_dir, application=None, test_type=None, env=None):
    # Ensure that the base `_temp/profiles/` directory exists before trying to
    # create a nested directory.
    if not os.path.exists(BASE_PROFILE_DIR):
        os.mkdir(BASE_PROFILE_DIR)

    if not profile_dir:
        full_profile_dir = mkdtemp(
            dir=BASE_PROFILE_DIR,
            prefix="fftool.",
            suffix=""
        )

    else:
        full_profile_dir = os.path.join(BASE_PROFILE_DIR, profile_dir)

        if os.path.exists(full_profile_dir):
            msg = "WARNING: Profile '{0}' already exists. Merging configs."
            Log.header(msg.format(full_profile_dir), 'XL', '-')

    prefs = Preferences()

    for path in prefs_paths(application, test_type, env):
        prefs.add_file(path)

    # Add the `fftool.profile.name` pref so we can go to about:config and see
    # what our current profile is.
    prefs.add([("fftool.profile.name", full_profile_dir)])

    profile = Profile(
        profile=full_profile_dir, restore=False, preferences=prefs())

    Log.header("Launching browser with the following user configs:")
    print(profile.summary())

    # this is the path to the created profile
    return full_profile_dir
Ejemplo n.º 23
0
    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)
def create_mozprofile(profile_dir, application=None, test_type=None, env=None):
    # Ensure that the base `_temp/profiles/` directory exists before trying to
    # create a nested directory.
    if not os.path.exists(BASE_PROFILE_DIR):
        os.mkdir(BASE_PROFILE_DIR)

    if not profile_dir:
        full_profile_dir = mkdtemp(dir=BASE_PROFILE_DIR,
                                   prefix="fftool.",
                                   suffix="")

    else:
        full_profile_dir = os.path.join(BASE_PROFILE_DIR, profile_dir)

        if os.path.exists(full_profile_dir):
            msg = "WARNING: Profile '{0}' already exists. Merging configs."
            Log.header(msg.format(full_profile_dir), 'XL', '-')

    prefs = Preferences()

    for path in prefs_paths(application, test_type, env):
        prefs.add_file(path)

    # Add the `fftool.profile.name` pref so we can go to about:config and see
    # what our current profile is.
    prefs.add([("fftool.profile.name", full_profile_dir)])

    profile = Profile(profile=full_profile_dir,
                      restore=False,
                      preferences=prefs())

    Log.header("Launching browser with the following user configs:")
    print(profile.summary())

    # this is the path to the created profile
    return full_profile_dir
Ejemplo n.º 25
0
    def run(self):
        self.profile_dir = os.path.join(tempfile.mkdtemp(suffix='.gaiaunittest'),
                                        'profile')
        shutil.copytree(self.profile, self.profile_dir)

        cmdargs = ['--runapp', 'Test Agent']
        if self.browser_arg:
            cmdargs += list(self.browser_arg)

        profile = Profile(profile=self.profile_dir)
        self.runner = Runner(binary=self.binary,
                             profile=profile,
                             clean_profile=False,
                             cmdargs=cmdargs,
                             symbols_path=self.symbols_path)
        self.runner.start()
Ejemplo n.º 26
0
    def run(self, profile=None, timeout=PROCESS_TIMEOUT, env=None, args=None):
        """Runs the given FirefoxRunner with the given Profile, waits
        for completion, then returns the process exit code
        """
        if profile is None:
            profile = Profile()
        self.profile = profile

        if self.binary is None and self.url:
            self.binary = self.download_build()

        runner = FirefoxRunner(profile=self.profile,
                               binary=self.binary,
                               env=env,
                               cmdargs=args)

        runner.start(timeout=timeout)
        return runner.wait()
Ejemplo n.º 27
0
    def start_runner(self, target, options):
        du = DeviceUtils(self.runner.device.dm)
        device = self.runner.device
        port = options.get('port')
        profile = Profile(profile=options.get('profile'))

        device.setup_port_forwarding(local_port=port, remote_port=port)

        du._stop_b2g()
        du._purge_data()
        du._purge_wifi_networks()
        du._purge_storage_data()

        self.runner.profile = profile
        self.runner.start()

        if not device.wait_for_port(port=port, timeout=600):
            raise Exception("Wait for port timed out")
Ejemplo n.º 28
0
    def build_profile(self, options):
        # preferences
        prefs = {}
        for path in self.preferences:
            prefs.update(Preferences.read_prefs(path))

        for v in options.extraPrefs:
            thispref = v.split("=", 1)
            if len(thispref) < 2:
                print "Error: syntax error in --setpref=" + v
                sys.exit(1)
            prefs[thispref[0]] = thispref[1]

        # interpolate the preferences
        interpolation = {
            "server": "%s:%s" %
            (options.webServer,
             options.httpPort),
            "OOP": "true" if self.out_of_process else "false"}
        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        kwargs = {
            'addons': self.getExtensionsToInstall(options),
            'apps': self.webapps,
            'locations': self.locations_file,
            'preferences': prefs,
            'proxy': {"remote": options.webServer}
        }

        if options.profile:
            self.profile = Profile.clone(options.profile, **kwargs)
        else:
            self.profile = Profile(**kwargs)

        options.profilePath = self.profile.profile
        # TODO bug 839108 - mozprofile should probably handle this
        manifest = self.addChromeToProfile(options)
        self.copyExtraFilesToProfile(options)
        return manifest
Ejemplo n.º 29
0
def tps_profile(pytestconfig, tps_addon, tps_config, tps_log, fxa_urls):
    preferences = {
        'app.update.enabled': False,
        'browser.dom.window.dump.enabled': True,
        'browser.onboarding.enabled': False,
        'browser.sessionstore.resume_from_crash': False,
        'browser.shell.checkDefaultBrowser': False,
        'browser.startup.homepage_override.mstone': 'ignore',
        'browser.startup.page': 0,
        'browser.tabs.warnOnClose': False,
        'browser.warnOnQuit': False,
        'datareporting.policy.dataSubmissionEnabled': False,
        # 'devtools.chrome.enabled': True,
        # 'devtools.debugger.remote-enabled': True,
        'engine.bookmarks.repair.enabled': False,
        'extensions.autoDisableScopes': 10,
        'extensions.legacy.enabled': True,
        'extensions.update.enabled': False,
        'extensions.update.notifyUser': False,
        # While this line is commented prod is launched instead of stage
        'identity.fxaccounts.autoconfig.uri': fxa_urls['content'],
        'testing.tps.skipPingValidation': True,
        'services.sync.firstSync': 'notReady',
        'services.sync.lastversion': '1.0',
        'services.sync.log.appender.console': 'Trace',
        'services.sync.log.appender.dump': 'Trace',
        'services.sync.log.appender.file.level': 'Trace',
        'services.sync.log.appender.file.logOnSuccess': True,
        'services.sync.log.logger': 'Trace',
        'services.sync.log.logger.engine': 'Trace',
        'services.sync.testing.tps': True,
        'testing.tps.logFile': tps_log,
        'toolkit.startup.max_resumed_crashes': -1,
        'tps.config': json.dumps(tps_config),
        'tps.seconds_since_epoch': int(time.time()),
        'xpinstall.signatures.required': False
    }
    profile = Profile(addons=[tps_addon], preferences=preferences)
    pytestconfig._profile = profile.profile
    yield profile
    def build_profile(self):
        """
           Create a local profile with test prefs and proxy definitions and
           push it to the remote device.
        """
        preferences = [
            os.path.join(
                here,
                'profile_data',
                'prefs_general.js')]

        prefs = {}
        for path in preferences:
            prefs.update(Preferences.read_prefs(path))

        interpolation = {
            "server": "%s:%s" %
            (self.options.webServer, self.options.httpPort)}

        prefs = json.loads(json.dumps(prefs) % interpolation)
        for pref in prefs:
            prefs[pref] = Preferences.cast(prefs[pref])

        proxy = {'remote': self.options.webServer,
                 'http': self.options.httpPort,
                 'https': self.options.sslPort,
                 'ws': self.options.sslPort
                 }

        self.profile = Profile(preferences=prefs, proxy=proxy)
        self.options.profilePath = self.profile.profile

        if self.fillCertificateDB(self.options):
            self.log.error("Certificate integration failed")

        self.device.mkdir(self.remote_profile, parents=True)
        self.device.push(self.profile.profile, self.remote_profile)
        self.log.debug("profile %s -> %s" %
                       (str(self.profile.profile), str(self.remote_profile)))
Ejemplo n.º 31
0
    def create_profile(self, custom_addons=[], custom_prefs=None, root=True):
        # Create, install and initialize the profile to be
        # used in the test.

        temp_addons = ['quitter.xpi']
        temp_addons.extend(custom_addons)
        addons = ['%s/xpi/%s' % (os.getcwd(), addon) for addon in temp_addons]

        # make sure firefox isn't running when we try to
        # install the profile.

        self.dm.pkill(self.build.app_name, root=root)
        if isinstance(custom_prefs, dict):
            prefs = dict(self.preferences.items() + custom_prefs.items())
        else:
            prefs = self.preferences
        profile = Profile(preferences=prefs, addons=addons)
        if not self.install_profile(profile):
            return False

        success = False
        for attempt in range(1, self.options.phone_retry_limit+1):
            self.loggerdeco.debug('Attempt %d Initializing profile', attempt)
            self.run_fennec_with_profile(self.build.app_name, self._initialize_url)

            if self.wait_for_fennec():
                success = True
                break
            sleep(self.options.phone_retry_wait)

        if not success or self.handle_crashes():
            self.add_failure(self.name, TestStatus.TEST_UNEXPECTED_FAIL,
                             'Failure initializing profile',
                             TreeherderStatus.TESTFAILED)

        return success
Ejemplo n.º 32
0
class GeckoInstance(object):

    required_prefs = {
        "marionette.defaultPrefs.enabled": True,
        "marionette.logging": True,
        "startup.homepage_welcome_url": "about:blank",
        "browser.shell.checkDefaultBrowser": False,
        "browser.startup.page": 0,
        "browser.sessionstore.resume_from_crash": False,
        "browser.warnOnQuit": False,
        "browser.displayedE10SPrompt": 5,
        "browser.displayedE10SPrompt.1": 5,
        "browser.displayedE10SPrompt.2": 5,
        "browser.displayedE10SPrompt.3": 5,
        "browser.displayedE10SPrompt.4": 5,
        "browser.tabs.remote.autostart.1": False,
        "browser.tabs.remote.autostart.2": False,
        "dom.ipc.reportProcessHangs": False,
    }

    def __init__(self, host, port, bin, profile=None, app_args=None, symbols_path=None, gecko_log=None, prefs=None):
        self.marionette_host = host
        self.marionette_port = port
        self.bin = bin
        # Check if it is a Profile object or a path to profile
        self.profile = None
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(GeckoInstance.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path
        self.gecko_log = gecko_log

    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update(
                {
                    "devtools.browsertoolbox.panel": "jsdebugger",
                    "devtools.debugger.remote-enabled": True,
                    "devtools.debugger.chrome-enabled": True,
                    "devtools.chrome.enabled": True,
                    "devtools.debugger.prompt-connection": False,
                    "marionette.debugging.clicktostart": True,
                }
            )

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                profile_args["restore"] = False
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                self.profile = Profile.clone(**profile_args)

        process_args = {"processOutputLine": [NullOutput()]}

        if self.gecko_log == "-":
            process_args["stream"] = sys.stdout
        else:
            if self.gecko_log is None:
                self.gecko_log = "gecko.log"
            elif os.path.isdir(self.gecko_log):
                fname = "gecko-%d.log" % time.time()
                self.gecko_log = os.path.join(self.gecko_log, fname)

            self.gecko_log = os.path.realpath(self.gecko_log)
            if os.access(self.gecko_log, os.F_OK):
                if platform.system() is "Windows":
                    # NOTE: windows has a weird filesystem where it happily 'closes'
                    # the file, but complains if you try to delete it. You get a
                    # 'file still in use' error. Sometimes you can wait a bit and
                    # a retry will succeed.
                    # If all retries fail, we'll just continue without removing
                    # the file. In this case, if we are restarting the instance,
                    # then the new logs just get appended to the old file.
                    tries = 0
                    while tries < 10:
                        try:
                            os.remove(self.gecko_log)
                            break
                        except WindowsError as e:
                            if e.errno == errno.EACCES:
                                tries += 1
                                time.sleep(0.5)
                            else:
                                raise e
                else:
                    os.remove(self.gecko_log)

            process_args["logfile"] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({"MOZ_CRASHREPORTER": "1", "MOZ_CRASHREPORTER_NO_REPORT": "1"})
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=["-no-remote", "-marionette"] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args,
        )
        self.runner.start()

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        if clean:
            self.profile.cleanup()
            self.profile = None

        self.close(restart=True)
        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 33
0
class GeckoInstance(object):
    required_prefs = {
        "browser.sessionstore.resume_from_crash": False,
        "browser.shell.checkDefaultBrowser": False,
        "browser.startup.page": 0,
        "browser.tabs.remote.autostart.1": False,
        "browser.tabs.remote.autostart.2": False,
        "browser.tabs.remote.autostart": False,
        "browser.urlbar.userMadeSearchSuggestionsChoice": True,
        "browser.warnOnQuit": False,
        "datareporting.healthreport.logging.consoleEnabled": False,
        "datareporting.healthreport.service.enabled": False,
        "datareporting.healthreport.service.firstRun": False,
        "datareporting.healthreport.uploadEnabled": False,
        "datareporting.policy.dataSubmissionEnabled": False,
        "datareporting.policy.dataSubmissionPolicyAccepted": False,
        "dom.ipc.reportProcessHangs": False,
        # Only install add-ons from the profile and the application scope
        # Also ensure that those are not getting disabled.
        # see: https://developer.mozilla.org/en/Installing_extensions
        "extensions.enabledScopes": 5,
        "extensions.autoDisableScopes": 10,
        "focusmanager.testmode": True,
        "marionette.defaultPrefs.enabled": True,
        "startup.homepage_welcome_url": "",
        "startup.homepage_welcome_url.additional": "",
        "toolkit.telemetry.enabled": False,
        # Until Bug 1238095 is fixed, we have to enable CPOWs in order
        # for Marionette tests to work properly.
        "dom.ipc.cpows.forbid-unsafe-from-browser": False,
    }

    def __init__(self, host, port, bin, profile=None, addons=None,
                 app_args=None, symbols_path=None, gecko_log=None, prefs=None,
                 workspace=None, verbose=0):
        self.runner_class = Runner
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path
        self.binary = bin

        self.marionette_host = host
        self.marionette_port = port
        # Alternative to default temporary directory
        self.workspace = workspace
        self.addons = addons
        # Check if it is a Profile object or a path to profile
        self.profile = None
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(self.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)

        self._gecko_log_option = gecko_log
        self._gecko_log = None
        self.verbose = verbose

    @property
    def gecko_log(self):
        if self._gecko_log:
            return self._gecko_log

        path = self._gecko_log_option
        if path != '-':
            if path is None:
                path = 'gecko.log'
            elif os.path.isdir(path):
                fname = 'gecko-%d.log' % time.time()
                path = os.path.join(path, fname)

            path = os.path.realpath(path)
            if os.access(path, os.F_OK):
                os.remove(path)

        self._gecko_log = path
        return self._gecko_log

    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

    def start(self):
        self._update_profile()
        self.runner = self.runner_class(**self._get_runner_args())
        self.runner.start()

    def _get_runner_args(self):
        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({'MOZ_CRASHREPORTER': '1',
                    'MOZ_CRASHREPORTER_NO_REPORT': '1'})

        return {
            'binary': self.binary,
            'profile': self.profile,
            'cmdargs': ['-no-remote', '-marionette'] + self.app_args,
            'env': env,
            'symbols_path': self.symbols_path,
            'process_args': process_args
        }

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean and self.profile:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 34
0
class GeckoInstance(object):
    required_prefs = {
        "browser.sessionstore.resume_from_crash": False,
        "browser.shell.checkDefaultBrowser": False,
        # Needed for branded builds to prevent opening a second tab on startup
        "browser.startup.homepage_override.mstone": "ignore",
        "browser.startup.page": 0,
        "browser.tabs.remote.autostart.1": False,
        "browser.tabs.remote.autostart.2": False,
        "browser.tabs.remote.autostart": False,
        "browser.urlbar.userMadeSearchSuggestionsChoice": True,
        "browser.warnOnQuit": False,
        "datareporting.healthreport.logging.consoleEnabled": False,
        "datareporting.healthreport.service.enabled": False,
        "datareporting.healthreport.service.firstRun": False,
        "datareporting.healthreport.uploadEnabled": False,
        "datareporting.policy.dataSubmissionEnabled": False,
        "datareporting.policy.dataSubmissionPolicyAccepted": False,
        "dom.ipc.reportProcessHangs": False,
        # Only install add-ons from the profile and the application scope
        # Also ensure that those are not getting disabled.
        # see: https://developer.mozilla.org/en/Installing_extensions
        "extensions.enabledScopes": 5,
        "extensions.autoDisableScopes": 10,
        "focusmanager.testmode": True,
        "marionette.defaultPrefs.enabled": True,
        "startup.homepage_welcome_url": "",
        "startup.homepage_welcome_url.additional": "",
        "toolkit.telemetry.enabled": False,
        # Until Bug 1238095 is fixed, we have to enable CPOWs in order
        # for Marionette tests to work properly.
        "dom.ipc.cpows.forbid-unsafe-from-browser": False,
    }

    def __init__(self, host, port, bin, profile=None, addons=None,
                 app_args=None, symbols_path=None, gecko_log=None, prefs=None,
                 workspace=None, verbose=0):
        self.runner_class = Runner
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path
        self.binary = bin

        self.marionette_host = host
        self.marionette_port = port
        # Alternative to default temporary directory
        self.workspace = workspace
        self.addons = addons
        # Check if it is a Profile object or a path to profile
        self.profile = None
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(self.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)

        self._gecko_log_option = gecko_log
        self._gecko_log = None
        self.verbose = verbose

    @property
    def gecko_log(self):
        if self._gecko_log:
            return self._gecko_log

        path = self._gecko_log_option
        if path != '-':
            if path is None:
                path = 'gecko.log'
            elif os.path.isdir(path):
                fname = 'gecko-{}.log'.format(time.time())
                path = os.path.join(path, fname)

            path = os.path.realpath(path)
            if os.access(path, os.F_OK):
                os.remove(path)

        self._gecko_log = path
        return self._gecko_log

    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

    def start(self):
        self._update_profile()
        self.runner = self.runner_class(**self._get_runner_args())
        self.runner.start()

    def _get_runner_args(self):
        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({'MOZ_CRASHREPORTER': '1',
                    'MOZ_CRASHREPORTER_NO_REPORT': '1',
                    'MOZ_CRASHREPORTER_SHUTDOWN': '1',
                    })

        return {
            'binary': self.binary,
            'profile': self.profile,
            'cmdargs': ['-no-remote', '-marionette'] + self.app_args,
            'env': env,
            'symbols_path': self.symbols_path,
            'process_args': process_args
        }

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean and self.profile:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 35
0
    def run_single_test(self, testdir, testname):
        testpath = os.path.join(testdir, testname)
        self.log("Running test %s\n" % testname, True)

        # Read and parse the test file, merge it with the contents of the config
        # file, and write the combined output to a temporary file.
        f = open(testpath, 'r')
        testcontent = f.read()
        f.close()
        # We use yaml to parse the tests because it is a superset of json
        # but tolerates things like property names not being quoted, trailing
        # commas, etc.
        try:
            test = yaml.safe_load(testcontent)
        except Exception:
            test = yaml.safe_load(
                testcontent[testcontent.find('{'):testcontent.find('}') + 1])

        self.preferences['tps.seconds_since_epoch'] = int(time.time())

        # generate the profiles defined in the test, and a list of test phases
        profiles = {}
        phaselist = []
        for phase in test:
            profilename = test[phase]

            # create the profile if necessary
            if profilename not in profiles:
                profiles[profilename] = Profile(
                    preferences=self.preferences.copy(),
                    addons=self.extensions)

            # create the test phase
            phaselist.append(
                TPSTestPhase(phase,
                             profiles[profilename],
                             testname,
                             testpath,
                             self.logfile,
                             self.env,
                             self.firefoxRunner,
                             self.log,
                             ignore_unused_engines=self.ignore_unused_engines))

        # sort the phase list by name
        phaselist = sorted(phaselist, key=lambda phase: phase.phase)

        # run each phase in sequence, aborting at the first failure
        failed = False
        for phase in phaselist:
            phase.run()
            if phase.status != 'PASS':
                failed = True
                break

        for profilename in profiles:
            print("### Cleanup Profile ", profilename)
            cleanup_phase = TPSTestPhase('cleanup-' + profilename,
                                         profiles[profilename], testname,
                                         testpath, self.logfile, self.env,
                                         self.firefoxRunner, self.log)

            cleanup_phase.run()
            if cleanup_phase.status != 'PASS':
                failed = True
                # Keep going to run the remaining cleanup phases.

        if failed:
            self.handle_phase_failure(profiles)

        # grep the log for FF and sync versions
        f = open(self.logfile)
        logdata = f.read()
        match = self.syncVerRe.search(logdata)
        sync_version = match.group('syncversion') if match else 'unknown'
        match = self.ffVerRe.search(logdata)
        firefox_version = match.group('ffver') if match else 'unknown'
        match = self.ffBuildIDRe.search(logdata)
        firefox_buildid = match.group('ffbuildid') if match else 'unknown'
        f.close()
        if phase.status == 'PASS':
            logdata = ''
        else:
            # we only care about the log data for this specific test
            logdata = logdata[logdata.find('Running test %s' %
                                           (str(testname))):]

        result = {
            'PASS': lambda x: ('TEST-PASS', ''),
            'FAIL': lambda x: ('TEST-UNEXPECTED-FAIL', x.rstrip()),
            'unknown': lambda x:
            ('TEST-UNEXPECTED-FAIL', 'test did not complete')
        }[phase.status](phase.errline)
        logstr = "\n%s | %s%s\n" % (result[0], testname,
                                    (' | %s' % result[1] if result[1] else ''))

        try:
            repoinfo = mozversion.get_version(self.binary)
        except Exception:
            repoinfo = {}
        apprepo = repoinfo.get('application_repository', '')
        appchangeset = repoinfo.get('application_changeset', '')

        # save logdata to a temporary file for posting to the db
        tmplogfile = None
        if logdata:
            tmplogfile = TempFile(prefix='tps_log_')
            tmplogfile.write(logdata)
            tmplogfile.close()
            self.errorlogs[testname] = tmplogfile

        resultdata = ({
            'productversion': {
                'version': firefox_version,
                'buildid': firefox_buildid,
                'builddate': firefox_buildid[0:8],
                'product': 'Firefox',
                'repository': apprepo,
                'changeset': appchangeset,
            },
            'addonversion': {
                'version': sync_version,
                'product': 'Firefox Sync'
            },
            'name': testname,
            'message': result[1],
            'state': result[0],
            'logdata': logdata
        })

        self.log(logstr, True)
        for phase in phaselist:
            print("\t{}: {}".format(phase.phase, phase.status))

        return resultdata
Ejemplo n.º 36
0
class GeckoInstance(object):
    required_prefs = {
        # Increase the APZ content response timeout in tests to 1 minute.
        # This is to accommodate the fact that test environments tends to be slower
        # than production environments (with the b2g emulator being the slowest of them
        # all), resulting in the production timeout value sometimes being exceeded
        # and causing false-positive test failures. See bug 1176798, bug 1177018,
        # bug 1210465.
        "apz.content_response_timeout": 60000,

        # Do not send Firefox health reports to the production server
        "datareporting.healthreport.documentServerURI": "http://%(server)s/dummy/healthreport/",
        "datareporting.healthreport.about.reportUrl": "http://%(server)s/dummy/abouthealthreport/",

        # Do not show datareporting policy notifications which can interfer with tests
        "datareporting.policy.dataSubmissionPolicyBypassNotification": True,

        # Until Bug 1238095 is fixed, we have to enable CPOWs in order
        # for Marionette tests to work properly.
        "dom.ipc.cpows.forbid-unsafe-from-browser": False,
        "dom.ipc.reportProcessHangs": False,

        # No slow script dialogs
        "dom.max_chrome_script_run_time": 0,
        "dom.max_script_run_time": 0,

        # Only load extensions from the application and user profile
        # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
        "extensions.autoDisableScopes": 0,
        "extensions.enabledScopes": 5,
        # don't block add-ons for e10s
        "extensions.e10sBlocksEnabling": False,
        # Disable metadata caching for installed add-ons by default
        "extensions.getAddons.cache.enabled": False,
        # Disable intalling any distribution add-ons
        "extensions.installDistroAddons": False,
        "extensions.showMismatchUI": False,
        # Turn off extension updates so they don't bother tests
        "extensions.update.enabled": False,
        "extensions.update.notifyUser": False,
        # Make sure opening about:addons won"t hit the network
        "extensions.webservice.discoverURL": "http://%(server)s/dummy/discoveryURL",

        # Allow the application to have focus even it runs in the background
        "focusmanager.testmode": True,

        # Disable useragent updates
        "general.useragent.updates.enabled": False,

        # Always use network provider for geolocation tests
        # so we bypass the OSX dialog raised by the corelocation provider
        "geo.provider.testing": True,
        # Do not scan Wifi
        "geo.wifi.scan": False,

        # No hang monitor
        "hangmonitor.timeout": 0,

        "javascript.options.showInConsole": True,
        "marionette.defaultPrefs.enabled": True,
        "media.volume_scale": "0.01",

        # Make sure the disk cache doesn't get auto disabled
        "network.http.bypass-cachelock-threshold": 200000,
        # Do not prompt for temporary redirects
        "network.http.prompt-temp-redirect": False,
        # Disable speculative connections so they aren"t reported as leaking when they"re
        # hanging around
        "network.http.speculative-parallel-limit": 0,
        # Do not automatically switch between offline and online
        "network.manage-offline-status": False,
        # Make sure SNTP requests don't hit the network
        "network.sntp.pools": "%(server)s",

        # Tests don't wait for the notification button security delay
        "security.notification_enable_delay": 0,

        # Ensure blocklist updates don't hit the network
        "services.settings.server": "http://%(server)s/dummy/blocklist/",

        # Disable password capture, so that tests that include forms aren"t
        # influenced by the presence of the persistent doorhanger notification
        "signon.rememberSignons": False,

        # Prevent starting into safe mode after application crashes
        "toolkit.startup.max_resumed_crashes": -1,

        # We want to collect telemetry, but we don't want to send in the results
        "toolkit.telemetry.server": "https://%(server)s/dummy/telemetry/",
    }

    def __init__(self, host=None, port=None, bin=None, profile=None, addons=None,
                 app_args=None, symbols_path=None, gecko_log=None, prefs=None,
                 workspace=None, verbose=0):
        self.runner_class = Runner
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path
        self.binary = bin

        self.marionette_host = host
        self.marionette_port = port
        # Alternative to default temporary directory
        self.workspace = workspace
        self.addons = addons
        # Check if it is a Profile object or a path to profile
        self.profile = None
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(self.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)

        self._gecko_log_option = gecko_log
        self._gecko_log = None
        self.verbose = verbose

    @property
    def gecko_log(self):
        if self._gecko_log:
            return self._gecko_log

        path = self._gecko_log_option
        if path != "-":
            if path is None:
                path = "gecko.log"
            elif os.path.isdir(path):
                fname = "gecko-{}.log".format(time.time())
                path = os.path.join(path, fname)

            path = os.path.realpath(path)
            if os.access(path, os.F_OK):
                os.remove(path)

        self._gecko_log = path
        return self._gecko_log

    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args["addons"] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args["profile"] = tempfile.mkdtemp(
                        suffix=".mozrunner-{:.0f}".format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = "{}-{:.0f}".format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

    @classmethod
    def create(cls, app=None, *args, **kwargs):
        try:
            if not app:
                app_id = mozversion.get_version(binary=kwargs.get('bin'))['application_id']
                app = app_ids[app_id]

            instance_class = apps[app]
        except KeyError:
            msg = 'Application "{0}" unknown (should be one of {1})'
            raise NotImplementedError(msg.format(app, apps.keys()))

        return instance_class(*args, **kwargs)

    def start(self):
        self._update_profile()
        self.runner = self.runner_class(**self._get_runner_args())
        self.runner.start()

    def _get_runner_args(self):
        process_args = {
            "processOutputLine": [NullOutput()],
        }

        if self.gecko_log == "-":
            process_args["stream"] = sys.stdout
        else:
            process_args["logfile"] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({"MOZ_CRASHREPORTER": "1",
                    "MOZ_CRASHREPORTER_NO_REPORT": "1",
                    "MOZ_CRASHREPORTER_SHUTDOWN": "1",
                    })

        return {
            "binary": self.binary,
            "profile": self.profile,
            "cmdargs": ["-no-remote", "-marionette"] + self.app_args,
            "env": env,
            "symbols_path": self.symbols_path,
            "process_args": process_args
        }

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean and self.profile:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 37
0
def test_with_profile_should_cleanup():
    with Profile() as profile:
        assert os.path.exists(profile.profile)

    # profile is cleaned
    assert not os.path.exists(profile.profile)
Ejemplo n.º 38
0
class GeckoInstance(object):
    required_prefs = {
        # Increase the APZ content response timeout in tests to 1 minute.
        # This is to accommodate the fact that test environments tends to be slower
        # than production environments (with the b2g emulator being the slowest of them
        # all), resulting in the production timeout value sometimes being exceeded
        # and causing false-positive test failures. See bug 1176798, bug 1177018,
        # bug 1210465.
        "apz.content_response_timeout": 60000,

        # Do not send Firefox health reports to the production server
        "datareporting.healthreport.documentServerURI":
        "http://%(server)s/dummy/healthreport/",
        "datareporting.healthreport.about.reportUrl":
        "http://%(server)s/dummy/abouthealthreport/",

        # Do not show datareporting policy notifications which can interfer with tests
        "datareporting.policy.dataSubmissionPolicyBypassNotification": True,
        "dom.ipc.reportProcessHangs": False,

        # No slow script dialogs
        "dom.max_chrome_script_run_time": 0,
        "dom.max_script_run_time": 0,

        # Only load extensions from the application and user profile
        # AddonManager.SCOPE_PROFILE + AddonManager.SCOPE_APPLICATION
        "extensions.autoDisableScopes": 0,
        "extensions.enabledScopes": 5,
        # don't block add-ons for e10s
        "extensions.e10sBlocksEnabling": False,
        # Disable metadata caching for installed add-ons by default
        "extensions.getAddons.cache.enabled": False,
        # Disable intalling any distribution add-ons
        "extensions.installDistroAddons": False,
        "extensions.showMismatchUI": False,
        # Turn off extension updates so they don't bother tests
        "extensions.update.enabled": False,
        "extensions.update.notifyUser": False,
        # Make sure opening about:addons won"t hit the network
        "extensions.webservice.discoverURL":
        "http://%(server)s/dummy/discoveryURL",

        # Allow the application to have focus even it runs in the background
        "focusmanager.testmode": True,

        # Disable useragent updates
        "general.useragent.updates.enabled": False,

        # Always use network provider for geolocation tests
        # so we bypass the OSX dialog raised by the corelocation provider
        "geo.provider.testing": True,
        # Do not scan Wifi
        "geo.wifi.scan": False,

        # No hang monitor
        "hangmonitor.timeout": 0,
        "javascript.options.showInConsole": True,

        # Enable Marionette component
        # (deprecated and can be removed when Firefox 60 ships)
        "marionette.enabled": True,
        "marionette.defaultPrefs.enabled": True,

        # Disable recommended automation prefs in CI
        "marionette.prefs.recommended": False,
        "media.volume_scale": "0.01",

        # Do not prompt for temporary redirects
        "network.http.prompt-temp-redirect": False,
        # Disable speculative connections so they aren"t reported as leaking when they"re
        # hanging around
        "network.http.speculative-parallel-limit": 0,
        # Do not automatically switch between offline and online
        "network.manage-offline-status": False,
        # Make sure SNTP requests don't hit the network
        "network.sntp.pools": "%(server)s",

        # Tests don't wait for the notification button security delay
        "security.notification_enable_delay": 0,

        # Ensure blocklist updates don't hit the network
        "services.settings.server": "http://%(server)s/dummy/blocklist/",

        # Disable password capture, so that tests that include forms aren"t
        # influenced by the presence of the persistent doorhanger notification
        "signon.rememberSignons": False,

        # Prevent starting into safe mode after application crashes
        "toolkit.startup.max_resumed_crashes": -1,

        # We want to collect telemetry, but we don't want to send in the results
        "toolkit.telemetry.server": "https://%(server)s/dummy/telemetry/",

        # Enabling the support for File object creation in the content process.
        "dom.file.createInChild": True,
    }

    def __init__(self,
                 host=None,
                 port=None,
                 bin=None,
                 profile=None,
                 addons=None,
                 app_args=None,
                 symbols_path=None,
                 gecko_log=None,
                 prefs=None,
                 workspace=None,
                 verbose=0,
                 headless=False):
        self.runner_class = Runner
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path
        self.binary = bin

        self.marionette_host = host
        self.marionette_port = port
        # Alternative to default temporary directory
        self.workspace = workspace
        self.addons = addons
        # Check if it is a Profile object or a path to profile
        self.profile = None
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(self.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)

        self._gecko_log_option = gecko_log
        self._gecko_log = None
        self.verbose = verbose
        self.headless = headless

    @property
    def gecko_log(self):
        if self._gecko_log:
            return self._gecko_log

        path = self._gecko_log_option
        if path != "-":
            if path is None:
                path = "gecko.log"
            elif os.path.isdir(path):
                fname = "gecko-{}.log".format(time.time())
                path = os.path.join(path, fname)

            path = os.path.realpath(path)
            if os.access(path, os.F_OK):
                os.remove(path)

        self._gecko_log = path
        return self._gecko_log

    def _update_profile(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"][
            "marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel":
                "jsdebugger",
                "devtools.debugger.remote-enabled":
                True,
                "devtools.chrome.enabled":
                True,
                "devtools.debugger.prompt-connection":
                False,
                "marionette.debugging.clicktostart":
                True,
            })
        if self.addons:
            profile_args["addons"] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args["profile"] = tempfile.mkdtemp(
                        suffix=".mozrunner-{:.0f}".format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = "{}-{:.0f}".format(
                    os.path.basename(self.profile_path), time.time())
                if self.workspace:
                    profile_args["path_to"] = os.path.join(
                        self.workspace, profile_name)
                self.profile = Profile.clone(**profile_args)

    @classmethod
    def create(cls, app=None, *args, **kwargs):
        try:
            if not app and kwargs["bin"] is not None:
                app_id = mozversion.get_version(
                    binary=kwargs["bin"])["application_id"]
                app = app_ids[app_id]

            instance_class = apps[app]
        except (IOError, KeyError):
            exc, val, tb = sys.exc_info()
            msg = 'Application "{0}" unknown (should be one of {1})'
            raise NotImplementedError, msg.format(app, apps.keys()), tb

        return instance_class(*args, **kwargs)

    def start(self):
        self._update_profile()
        self.runner = self.runner_class(**self._get_runner_args())
        self.runner.start()

    def _get_runner_args(self):
        process_args = {
            "processOutputLine": [NullOutput()],
        }

        if self.gecko_log == "-":
            process_args["stream"] = sys.stdout
        else:
            process_args["logfile"] = self.gecko_log

        env = os.environ.copy()

        if self.headless:
            env["MOZ_HEADLESS"] = "1"
            env["DISPLAY"] = "77"  # Set a fake display.

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({
            "MOZ_CRASHREPORTER": "1",
            "MOZ_CRASHREPORTER_NO_REPORT": "1",
            "MOZ_CRASHREPORTER_SHUTDOWN": "1",
        })

        return {
            "binary": self.binary,
            "profile": self.profile,
            "cmdargs": ["-no-remote", "-marionette"] + self.app_args,
            "env": env,
            "symbols_path": self.symbols_path,
            "process_args": process_args
        }

    def close(self, clean=False):
        """
        Close the managed Gecko process.

        Depending on self.runner_class, setting `clean` to True may also kill
        the emulator process in which this instance is running.

        :param clean: If True, also perform runner cleanup.
        """
        if self.runner:
            self.runner.stop()
            if clean:
                self.runner.cleanup()

        if clean and self.profile:
            self.profile.cleanup()
            self.profile = None

    def restart(self, prefs=None, clean=True):
        """
        Close then start the managed Gecko process.

        :param prefs: Dictionary of preference names and values.
        :param clean: If True, reset the profile before starting.
        """
        self.close(clean=clean)

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 39
0
class GeckoInstance(object):

    required_prefs = {"marionette.defaultPrefs.enabled": True,
                      "marionette.logging": True,
                      "browser.displayedE10SPrompt": 5,
                      "browser.displayedE10SPrompt.1": 5,
                      "browser.displayedE10SPrompt.2": 5,
                      "browser.displayedE10SPrompt.3": 5,
                      "browser.displayedE10SPrompt.4": 5,
                      "browser.sessionstore.resume_from_crash": False,
                      "browser.shell.checkDefaultBrowser": False,
                      "browser.startup.page": 0,
                      "browser.tabs.remote.autostart.1": False,
                      "browser.tabs.remote.autostart.2": False,
                      "browser.warnOnQuit": False,
                      "dom.ipc.reportProcessHangs": False,
                      "focusmanager.testmode": True,
                      "startup.homepage_welcome_url": "about:blank"}

    def __init__(self, host, port, bin, profile=None, addons=None,
                 app_args=None, symbols_path=None, gecko_log=None, prefs=None):
        self.marionette_host = host
        self.marionette_port = port
        self.bin = bin
        # Check if it is a Profile object or a path to profile
        self.profile = None
        self.addons = addons
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(GeckoInstance.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path

        if gecko_log != '-':
            if gecko_log is None:
                gecko_log = 'gecko.log'
            elif os.path.isdir(gecko_log):
                fname = 'gecko-%d.log' % time.time()
                gecko_log = os.path.join(gecko_log, fname)

            gecko_log = os.path.realpath(gecko_log)
            if os.access(gecko_log, os.F_OK):
                os.remove(gecko_log)

        self.gecko_log = gecko_log

    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args)
        self.runner.start()

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 40
0
class GeckoInstance(object):
    required_prefs = {
        "browser.displayedE10SPrompt.1": 5,
        "browser.displayedE10SPrompt.2": 5,
        "browser.displayedE10SPrompt.3": 5,
        "browser.displayedE10SPrompt.4": 5,
        "browser.displayedE10SPrompt": 5,
        "browser.sessionstore.resume_from_crash": False,
        "browser.shell.checkDefaultBrowser": False,
        "browser.startup.page": 0,
        "browser.tabs.remote.autostart.1": False,
        "browser.tabs.remote.autostart.2": False,
        "browser.tabs.remote.autostart": False,
        "browser.urlbar.userMadeSearchSuggestionsChoice": True,
        "browser.warnOnQuit": False,
        "datareporting.healthreport.logging.consoleEnabled": False,
        "datareporting.healthreport.service.enabled": False,
        "datareporting.healthreport.service.firstRun": False,
        "datareporting.healthreport.uploadEnabled": False,
        "datareporting.policy.dataSubmissionEnabled": False,
        "datareporting.policy.dataSubmissionPolicyAccepted": False,
        "dom.ipc.reportProcessHangs": False,
        "focusmanager.testmode": True,
        "marionette.defaultPrefs.enabled": True,
        "startup.homepage_welcome_url": "about:blank",
        "toolkit.telemetry.enabled": False,
    }

    def __init__(self, host, port, bin, profile=None, addons=None,
                 app_args=None, symbols_path=None, gecko_log=None, prefs=None,
                 workspace=None, verbose=0):
        self.marionette_host = host
        self.marionette_port = port
        self.bin = bin
        # Alternative to default temporary directory
        self.workspace = workspace
        # Check if it is a Profile object or a path to profile
        self.profile = None
        self.addons = addons
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(GeckoInstance.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path

        if gecko_log != '-':
            if gecko_log is None:
                gecko_log = 'gecko.log'
            elif os.path.isdir(gecko_log):
                fname = 'gecko-%d.log' % time.time()
                gecko_log = os.path.join(gecko_log, fname)

            gecko_log = os.path.realpath(gecko_log)
            if os.access(gecko_log, os.F_OK):
                os.remove(gecko_log)

        self.gecko_log = gecko_log
        self.verbose = verbose

    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if '-jsdebugger' in self.app_args:
            profile_args["preferences"].update({
                "devtools.browsertoolbox.panel": "jsdebugger",
                "devtools.debugger.remote-enabled": True,
                "devtools.chrome.enabled": True,
                "devtools.debugger.prompt-connection": False,
                "marionette.debugging.clicktostart": True,
            })
        if self.addons:
            profile_args['addons'] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args['profile'] = tempfile.mkdtemp(
                        suffix='.mozrunner-{:.0f}'.format(time.time()),
                        dir=self.workspace)
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = '{}-{:.0f}'.format(
                    os.path.basename(self.profile_path),
                    time.time()
                )
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace,
                                                           profile_name)
                self.profile = Profile.clone(**profile_args)

        process_args = {
            'processOutputLine': [NullOutput()],
        }

        if self.gecko_log == '-':
            process_args['stream'] = sys.stdout
        else:
            process_args['logfile'] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({ 'MOZ_CRASHREPORTER': '1',
                     'MOZ_CRASHREPORTER_NO_REPORT': '1', })
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=['-no-remote', '-marionette'] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args)
        self.runner.start()

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()
Ejemplo n.º 41
0
 def test_with_profile_should_cleanup(self):
     with Profile() as profile:
         self.assertTrue(os.path.exists(profile.profile))
     # profile is cleaned
     self.assertFalse(os.path.exists(profile.profile))
Ejemplo n.º 42
0
    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update(
                {
                    "devtools.browsertoolbox.panel": "jsdebugger",
                    "devtools.debugger.remote-enabled": True,
                    "devtools.debugger.chrome-enabled": True,
                    "devtools.chrome.enabled": True,
                    "devtools.debugger.prompt-connection": False,
                    "marionette.debugging.clicktostart": True,
                }
            )

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                profile_args["restore"] = False
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                self.profile = Profile.clone(**profile_args)

        process_args = {"processOutputLine": [NullOutput()]}

        if self.gecko_log == "-":
            process_args["stream"] = sys.stdout
        else:
            if self.gecko_log is None:
                self.gecko_log = "gecko.log"
            elif os.path.isdir(self.gecko_log):
                fname = "gecko-%d.log" % time.time()
                self.gecko_log = os.path.join(self.gecko_log, fname)

            self.gecko_log = os.path.realpath(self.gecko_log)
            if os.access(self.gecko_log, os.F_OK):
                if platform.system() is "Windows":
                    # NOTE: windows has a weird filesystem where it happily 'closes'
                    # the file, but complains if you try to delete it. You get a
                    # 'file still in use' error. Sometimes you can wait a bit and
                    # a retry will succeed.
                    # If all retries fail, we'll just continue without removing
                    # the file. In this case, if we are restarting the instance,
                    # then the new logs just get appended to the old file.
                    tries = 0
                    while tries < 10:
                        try:
                            os.remove(self.gecko_log)
                            break
                        except WindowsError as e:
                            if e.errno == errno.EACCES:
                                tries += 1
                                time.sleep(0.5)
                            else:
                                raise e
                else:
                    os.remove(self.gecko_log)

            process_args["logfile"] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({"MOZ_CRASHREPORTER": "1", "MOZ_CRASHREPORTER_NO_REPORT": "1"})
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=["-no-remote", "-marionette"] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args,
        )
        self.runner.start()
Ejemplo n.º 43
0
class GeckoInstance(object):
    required_prefs = {
        "browser.sessionstore.resume_from_crash": False,
        "browser.shell.checkDefaultBrowser": False,
        "browser.startup.page": 0,
        "browser.tabs.remote.autostart.1": False,
        "browser.tabs.remote.autostart.2": False,
        "browser.tabs.remote.autostart": False,
        "browser.urlbar.userMadeSearchSuggestionsChoice": True,
        "browser.warnOnQuit": False,
        "datareporting.healthreport.logging.consoleEnabled": False,
        "datareporting.healthreport.service.enabled": False,
        "datareporting.healthreport.service.firstRun": False,
        "datareporting.healthreport.uploadEnabled": False,
        "datareporting.policy.dataSubmissionEnabled": False,
        "datareporting.policy.dataSubmissionPolicyAccepted": False,
        "dom.ipc.reportProcessHangs": False,
        # Only install add-ons from the profile and the application scope
        # Also ensure that those are not getting disabled.
        # see: https://developer.mozilla.org/en/Installing_extensions
        "extensions.enabledScopes": 5,
        "extensions.autoDisableScopes": 10,
        "focusmanager.testmode": True,
        "marionette.defaultPrefs.enabled": True,
        "startup.homepage_welcome_url": "about:blank",
        "toolkit.telemetry.enabled": False,
        # Until Bug 1238095 is fixed, we have to enable CPOWs in order
        # for Marionette tests to work properly.
        "dom.ipc.cpows.forbid-unsafe-from-browser": False,
    }

    def __init__(
        self,
        host,
        port,
        bin,
        profile=None,
        addons=None,
        app_args=None,
        symbols_path=None,
        gecko_log=None,
        prefs=None,
        workspace=None,
        verbose=0,
    ):
        self.marionette_host = host
        self.marionette_port = port
        self.bin = bin
        # Alternative to default temporary directory
        self.workspace = workspace
        # Check if it is a Profile object or a path to profile
        self.profile = None
        self.addons = addons
        if isinstance(profile, Profile):
            self.profile = profile
        else:
            self.profile_path = profile
        self.prefs = prefs
        self.required_prefs = deepcopy(GeckoInstance.required_prefs)
        if prefs:
            self.required_prefs.update(prefs)
        self.app_args = app_args or []
        self.runner = None
        self.symbols_path = symbols_path

        if gecko_log != "-":
            if gecko_log is None:
                gecko_log = "gecko.log"
            elif os.path.isdir(gecko_log):
                fname = "gecko-%d.log" % time.time()
                gecko_log = os.path.join(gecko_log, fname)

            gecko_log = os.path.realpath(gecko_log)
            if os.access(gecko_log, os.F_OK):
                os.remove(gecko_log)

        self.gecko_log = gecko_log
        self.verbose = verbose

    def start(self):
        profile_args = {"preferences": deepcopy(self.required_prefs)}
        profile_args["preferences"]["marionette.defaultPrefs.port"] = self.marionette_port
        if self.prefs:
            profile_args["preferences"].update(self.prefs)
        if self.verbose:
            level = "TRACE" if self.verbose >= 2 else "DEBUG"
            profile_args["preferences"]["marionette.logging"] = level
        if "-jsdebugger" in self.app_args:
            profile_args["preferences"].update(
                {
                    "devtools.browsertoolbox.panel": "jsdebugger",
                    "devtools.debugger.remote-enabled": True,
                    "devtools.chrome.enabled": True,
                    "devtools.debugger.prompt-connection": False,
                    "marionette.debugging.clicktostart": True,
                }
            )
        if self.addons:
            profile_args["addons"] = self.addons

        if hasattr(self, "profile_path") and self.profile is None:
            if not self.profile_path:
                if self.workspace:
                    profile_args["profile"] = tempfile.mkdtemp(
                        suffix=".mozrunner-{:.0f}".format(time.time()), dir=self.workspace
                    )
                self.profile = Profile(**profile_args)
            else:
                profile_args["path_from"] = self.profile_path
                profile_name = "{}-{:.0f}".format(os.path.basename(self.profile_path), time.time())
                if self.workspace:
                    profile_args["path_to"] = os.path.join(self.workspace, profile_name)
                self.profile = Profile.clone(**profile_args)

        process_args = {"processOutputLine": [NullOutput()]}

        if self.gecko_log == "-":
            process_args["stream"] = sys.stdout
        else:
            process_args["logfile"] = self.gecko_log

        env = os.environ.copy()

        # environment variables needed for crashreporting
        # https://developer.mozilla.org/docs/Environment_variables_affecting_crash_reporting
        env.update({"MOZ_CRASHREPORTER": "1", "MOZ_CRASHREPORTER_NO_REPORT": "1"})
        self.runner = Runner(
            binary=self.bin,
            profile=self.profile,
            cmdargs=["-no-remote", "-marionette"] + self.app_args,
            env=env,
            symbols_path=self.symbols_path,
            process_args=process_args,
        )
        self.runner.start()

    def close(self, restart=False):
        if not restart:
            self.profile = None

        if self.runner:
            self.runner.stop()
            self.runner.cleanup()

    def restart(self, prefs=None, clean=True):
        self.close(restart=True)

        if clean:
            self.profile.cleanup()
            self.profile = None

        if prefs:
            self.prefs = prefs
        else:
            self.prefs = None
        self.start()