def runprofile(binary, fileobj): try: runner = FirefoxRunner(binary=binary, profile=fileobj.profile) runner.start() runner.wait() except KeyboardInterrupt: pass
def run(self, test, phase='phase1', ignore_unused_engines=True): self.profile.set_preferences({ 'testing.tps.testFile': os.path.abspath(test), 'testing.tps.testPhase': phase, 'testing.tps.ignoreUnusedEngines': ignore_unused_engines, }) args = ['-marionette'] process_args = {'processOutputLine': [self._log]} self.logger.info('Running: {} {}'.format(self.firefox, ' '.join(args))) self.logger.info('Using profile at: {}'.format(self.profile.profile)) runner = FirefoxRunner( binary=self.firefox, cmdargs=args, profile=self.profile, process_args=process_args) runner.start(timeout=TIMEOUT) runner.wait(timeout=TIMEOUT) self.firefox_log.close() with open(self.tps_log) as f: for line in f.readlines(): if 'CROSSWEAVE ERROR: ' in line: raise TPSError(line.partition('CROSSWEAVE ERROR: ')[-1]) with open(self.tps_log) as f: assert 'test phase {}: PASS'.format(phase) in f.read()
def run(self, test, phase='phase1', ignore_unused_engines=True): args = [ '-tps={}'.format(os.path.abspath(test)), '-tpsphase={}'.format(phase), '-marionette'] if ignore_unused_engines: args.append('--ignore-unused-engines') process_args = {'processOutputLine': [self._log]} self.logger.info('Running: {} {}'.format(self.firefox, ' '.join(args))) self.logger.info('Using profile at: {}'.format(self.profile.profile)) runner = FirefoxRunner( binary=self.firefox, cmdargs=args, profile=self.profile, process_args=process_args) runner.start(timeout=TIMEOUT) runner.wait(timeout=TIMEOUT) self.firefox_log.close() with open(self.tps_log) as f: for line in f.readlines(): if 'CROSSWEAVE ERROR: ' in line: raise TPSError(line.partition('CROSSWEAVE ERROR: ')[-1]) with open(self.tps_log) as f: assert 'test phase {}: PASS'.format(phase) in f.read()
def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations( filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, proxy=True, preferences=preferences) self.profile.set_preferences({ "marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False }) self.runner = FirefoxRunner( profile=self.profile, binary=self.binary, cmdargs=[cmd_arg("marionette"), "about:blank"], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=self.debug_args, interactive=self.interactive) self.logger.debug("Firefox Started")
class FFRunner(): # Calls FirefoxRunner with the right parameters def __init__(self, name="firefox", installDir=os.path.join(os.path.expanduser("~"),"remotebisectorapp")): self.name = name platform=get_platform() if platform['name'] == "Windows": if platform['bits'] == '64': print "No builds available for 64 bit Windows" sys.exit() self.buildRegex = ".*win32.zip" self.processName = self.name + ".exe" self.binary = os.path.join(installDir, self.name, self.name + ".exe") elif platform['name'] == "Linux": self.processName = self.name + "-bin" self.binary = os.path.join(installDir, self.name, self.name) if platform['bits'] == '64': self.buildRegex = ".*linux-x86_64.tar.bz2" else: self.buildRegex = ".*linux-i686.tar.bz2" elif platform['name'] == "Mac": self.buildRegex = ".*mac.*\.dmg" self.processName = self.name + "-bin" self.binary = os.path.join(installDir, "Mozilla.app/Contents/MacOS", self.name + "-bin") def run(self): self.runner = FirefoxRunner(binary=self.binary) self.runner.start()
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
def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) env = os.environ.copy() env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({"marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames)}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command(self.binary, [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations( filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({ "marionette.enabled": True, "marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False }) if self.e10s: self.profile.set_preferences( {"browser.tabs.remote.autostart": True}) # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences( {"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command( self.binary, [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner( profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
def start(self): """Start an instance of Firefox, returning a BrowserInstance handle""" profile = self.base_profile.clone(self.base_profile.profile) marionette_port = get_free_port() profile.set_preferences({"marionette.port": marionette_port}) env = test_environment(xrePath=os.path.dirname(self.binary), debugger=self.debug_info is not None, useLSan=True, log=self.logger) env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) if self.headless: env["MOZ_HEADLESS"] = "1" if self.enable_webrender: env["MOZ_WEBRENDER"] = "1" env["MOZ_ACCELERATED"] = "1" # Set MOZ_X_SYNC and GDK_SYNCHRONIZE for investigation; bug 1625250. env["MOZ_X_SYNC"] = "1" env["GDK_SYNCHRONIZE"] = "1" else: env["MOZ_WEBRENDER"] = "0" args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"] debug_args, cmd = browser_command(self.binary, args, self.debug_info) if self.leak_check: leak_report_file = os.path.join( profile.profile, "runtests_leaks_%s.log" % os.getpid()) if os.path.exists(leak_report_file): os.remove(leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = leak_report_file else: leak_report_file = None output_handler = OutputHandler(self.logger, self.stackfix_dir, self.symbols_path, self.asan) runner = FirefoxRunner( profile=profile, binary=cmd[0], cmdargs=cmd[1:], env=cast_env(env), process_class=ProcessHandler, process_args={"processOutputLine": [output_handler]}) instance = BrowserInstance(self.logger, runner, marionette_port, output_handler, leak_report_file) self.logger.debug("Starting Firefox") runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started") return instance
def run_tests(self, test_path, options): reftestlist = self.getManifestPath(test_path) if not reftestlist.startswith('file://'): reftestlist = 'file://%s' % reftestlist self.profile = self.create_profile(options, reftestlist, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line( options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status
def launch_firefox(path, profile=None, url=None, args=None): """Launch the app with optional args for profile, windows, URI, etc. :param path: Firefox path. :param profile: Firefox profile. :param url: URL to be loaded. :param args: Optional list of arguments. :return: List of Firefox flags. """ if args is None: args = [] if profile is None: raise APIHelperError('No profile name present, aborting run.') profile = FirefoxProfile(profile=profile) args.append('-foreground') args.append('-no-remote') if url is not None: args.append('-new-tab') args.append(url) process_args = {'stream': None} logger.debug('Creating Firefox runner ...') try: runner = FirefoxRunner(binary=path, profile=profile, cmdargs=args, process_args=process_args) logger.debug('Firefox runner successfully created.') logger.debug('Running Firefox with command: "%s"' % ','.join(runner.command)) return runner except errors.RunnerNotStartedError: raise APIHelperError('Error creating Firefox runner.')
def launch(self, args=None): """Launch the app with optional args for profile, windows, URI, etc. :param url: URL to be loaded. :param args: Optional list of arguments. :return: List of Firefox flags. """ if args is None: args = [] args.append('-foreground') args.append('-no-remote') args.append('-new-tab') args.append(self.url) process_args = {'stream': None} logger.debug('Creating Firefox runner ...') try: runner = FirefoxRunner(binary=self.application.path, profile=self.profile, cmdargs=args, process_args=process_args) logger.debug('Firefox runner successfully created.') logger.debug('Running Firefox with command: "%s"' % ','.join(runner.command)) except run_errors.RunnerNotStartedError: raise APIHelperError('Error creating Firefox runner.') else: return runner
def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() ports = {"http": "8000", "https": "8443", "ws": "8888"} self.profile = FirefoxProfile(locations=locations, proxy=ports, preferences=preferences) self.profile.set_preferences({"marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False}) self.runner = FirefoxRunner(profile=self.profile, binary=self.binary, cmdargs=[cmd_arg("marionette"), "about:blank"], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=self.debug_args, interactive=self.interactive) self.logger.debug("Firefox Started")
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() status = self.runner.process_handler.waitForFinish(timeout=timeout) return status
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()
def start(self, **kwargs): if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" env["STYLO_THREADS"] = str(self.stylo_threads) locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({"marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False, "dom.send_after_paint_to_content": True}) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences({"layout.interruptible-reflow.enabled": False}) if self.leak_check and kwargs.get("check_leaks", True): self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks.log") if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences({"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command(self.binary, self.binary_args if self.binary_args else [] + [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
def run(self): #Run the built binary if it exists. ONLY WORKS IF BUILD WAS CALLED! if sys.platform == "darwin": runner = FirefoxRunner.create(binary=os.path.join(self.shellCacheDir,"mozbuild-trunk","obj-ff-dbg","dist","NightlyDebug.app","Contents","MacOS")+"/firefox-bin") runner.start() runner.wait() elif sys.platform == "linux2": runner = FirefoxRunner.create(binary=os.path.join(self.shellCacheDir,"mozbuild-trunk","obj-ff-dbg","dist","bin") + "/firefox") runner.start() runner.wait() elif sys.platform == "win32" or sys.platform == "cygwin": runner = FirefoxRunner.create(binary=os.path.join(self.shellCacheDir,"mozbuild-trunk","obj-ff-dbg","dist","bin") + "/firefox.exe") runner.start() runner.wait() else: print "Your platform is not currently supported." quit()
def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) self._populate_logger(options) outputHandler = OutputHandler(self.log, options.utilityPath, symbolsPath=options.symbolsPath) kp_kwargs = { 'processOutputLine': [outputHandler], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 self.log.info("%s | Running tests: start." % os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) self.log.info("%s | Application pid: %d" % ( os.path.basename(__file__), self.runner.process_handler.pid)) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: self.log.testFail("%s | application terminated with exit code %s" % ( self.last_test, status)) elif status < 0: self.log.info("%s | application killed with signal %s" % ( self.last_test, -status)) self.log.info("%s | Running tests: end." % os.path.basename(__file__)) return status
def start(self): """Start an instance of Firefox, returning a BrowserInstance handle""" profile = self.base_profile.clone(self.base_profile.profile) marionette_port = get_free_port() profile.set_preferences({"marionette.port": marionette_port}) env = get_environ(self.logger, self.binary, self.debug_info, self.stylo_threads, self.headless, self.enable_webrender, self.chaos_mode_flags) args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"] debug_args, cmd = browser_command(self.binary, args, self.debug_info) if self.leak_check: leak_report_file = os.path.join( profile.profile, "runtests_leaks_%s.log" % os.getpid()) if os.path.exists(leak_report_file): os.remove(leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = leak_report_file else: leak_report_file = None output_handler = OutputHandler(self.logger, self.stackfix_dir, self.symbols_path, self.asan) runner = FirefoxRunner( profile=profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [output_handler]}) instance = BrowserInstance(self.logger, runner, marionette_port, output_handler, leak_report_file) self.logger.debug("Starting Firefox") runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started") return instance
def start_firefox(self): env = os.environ.copy() env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' profile = Profile() profile.set_preferences({"marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False, "dom.max_script_run_time": 0}) self.firefox_runner = FirefoxRunner(profile, self.firefox_binary, cmdargs=["--marionette"], env=env, kp_kwargs = {"processOutputLine":[self.on_output]}, process_class=self.process_cls) self.logger.debug("Starting Firefox") self.firefox_runner.start() self.logger.debug("Firefox Started")
def start(self): """Start an instance of Firefox, returning a BrowserInstance handle""" profile = self.base_profile.clone(self.base_profile.profile) marionette_port = get_free_port() profile.set_preferences({"marionette.port": marionette_port}) env = get_environ(self.logger, self.binary, self.debug_info, self.stylo_threads, self.headless, self.chaos_mode_flags) args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"] debug_args, cmd = browser_command(self.binary, args, self.debug_info) leak_report_file = setup_leak_report(self.leak_check, profile, env) output_handler = FirefoxOutputHandler( self.logger, cmd, stackfix_dir=self.stackfix_dir, symbols_path=self.symbols_path, asan=self.asan, leak_report_file=leak_report_file) runner = FirefoxRunner( profile=profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [output_handler]}) instance = BrowserInstance(self.logger, runner, marionette_port, output_handler, leak_report_file) self.logger.debug("Starting Firefox") runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) output_handler.after_process_start(runner.process_handler.pid) self.logger.debug("Firefox Started") return instance
def run_tests(self, test_path, options): reftestlist = self.getManifestPath(test_path) if not reftestlist.startswith('file://'): reftestlist = 'file://%s' % reftestlist self.profile = self.create_profile(options, reftestlist, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, symbols_path=options.symbolsPath, kp_kwargs=kp_kwargs) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status
def run(self, test, phase='phase1', ignore_unused_engines=True): self.profile.set_preferences({ 'testing.tps.testFile': os.path.abspath(test), 'testing.tps.testPhase': phase, 'testing.tps.ignoreUnusedEngines': ignore_unused_engines, }) args = ['-marionette'] process_args = {'processOutputLine': [self._log]} self.logger.info('Running: {} {}'.format(self.firefox, ' '.join(args))) self.logger.info('Using profile at: {}'.format(self.profile.profile)) runner = FirefoxRunner(binary=self.firefox, cmdargs=args, profile=self.profile, process_args=process_args) runner.start(timeout=TIMEOUT) runner.wait(timeout=TIMEOUT) self.firefox_log.close() with open(self.tps_log) as f: for line in f.readlines(): if 'CROSSWEAVE ERROR: ' in line: raise TPSError(line.partition('CROSSWEAVE ERROR: ')[-1]) with open(self.tps_log) as f: assert 'test phase {}: PASS'.format(phase) in f.read()
def launch_control_center(): profile_path = os.path.join(get_core_args().workdir, 'cc_profile') fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error( 'Can\'t find local Firefox installation, aborting Iris run.') return False, None args = ['http://127.0.0.1:%s' % get_core_args().port] process_args = {'stream': None} profile = MozProfile(profile=profile_path, preferences=Settings.default_fx_prefs) fx_runner = FirefoxRunner(binary=fx_path, profile=profile, cmdargs=args, process_args=process_args) fx_runner.start() server = LocalWebServer(get_core_args().workdir, get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text='q', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='w', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='q', modifier=KeyModifier.CTRL) try: fx_runner.stop() except Exception as e: logger.debug('Error stopping fx_runner') logger.debug(e) return server.result
def run(self, test, phase='phase1', ignore_unused_engines=True): args = [ '-tps={}'.format(os.path.abspath(test)), '-tpsphase={}'.format(phase), '-marionette' ] if ignore_unused_engines: args.append('--ignore-unused-engines') process_args = {'processOutputLine': [self._log]} self.logger.info('Running: {} {}'.format(self.firefox, ' '.join(args))) self.logger.info('Using profile at: {}'.format(self.profile.profile)) runner = FirefoxRunner(binary=self.firefox, cmdargs=args, profile=self.profile, process_args=process_args) runner.start(timeout=TIMEOUT) runner.wait(timeout=TIMEOUT) self.firefox_log.close() with open(self.tps_log) as f: for line in f.readlines(): if 'CROSSWEAVE ERROR: ' in line: raise TPSError(line.partition('CROSSWEAVE ERROR: ')[-1]) with open(self.tps_log) as f: assert 'test phase {}: PASS'.format(phase) in f.read()
def launch_control_center(): profile_path = os.path.join(PathManager.get_working_dir(), "cc_profile") fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error("Can't find local Firefox installation, aborting Iris run.") return False, None args = ["http://127.0.0.1:%s" % get_core_args().port] process_args = {"stream": None} profile = MozProfile(profile=profile_path, preferences=get_fx_prefs()) if OSHelper.is_windows(): process = subprocess.Popen( [ fx_path, "-no-remote", "-new-tab", args, "--wait-for-browser", "-foreground", "-profile", profile.profile, ], shell=False, ) else: fx_runner = FirefoxRunner( binary=fx_path, profile=profile, cmdargs=args, process_args=process_args ) fx_runner.start() logger.debug("Launching web server for directory %s" % PathManager.get_working_dir()) server = LocalWebServer(PathManager.get_working_dir(), get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text="q", modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text="w", modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text="q", modifier=KeyModifier.CTRL) if OSHelper.is_windows(): if process.pid is not None: try: logger.debug("Closing Firefox process ID: %s" % process.pid) process = psutil.Process(process.pid) for proc in process.children(recursive=True): proc.kill() process.kill() except psutil.NoSuchProcess: pass else: try: fx_runner.stop() except Exception as e: logger.debug("Error stopping fx_runner") logger.debug(e) return server.result
def run(self): #Run the built binary if it exists. ONLY WORKS IF BUILD WAS CALLED! if sys.platform == "darwin": runner = FirefoxRunner.create(binary=os.path.join( self.shellCacheDir, "mozbuild-trunk", "obj-ff-dbg", "dist", "NightlyDebug.app", "Contents", "MacOS") + "/firefox-bin") runner.start() runner.wait() elif sys.platform == "linux2": runner = FirefoxRunner.create( binary=os.path.join(self.shellCacheDir, "mozbuild-trunk", "obj-ff-dbg", "dist", "bin") + "/firefox") runner.start() runner.wait() elif sys.platform == "win32" or sys.platform == "cygwin": runner = FirefoxRunner.create( binary=os.path.join(self.shellCacheDir, "mozbuild-trunk", "obj-ff-dbg", "dist", "bin") + "/firefox.exe") runner.start() runner.wait() else: print "Your platform is not currently supported." quit()
def launch_control_center(): profile_path = os.path.join(get_core_args().workdir, 'cc_profile') fx_path = PathManager.get_local_firefox_path() if fx_path is None: logger.error( 'Can\'t find local Firefox installation, aborting Iris run.') return False, None args = ['http://127.0.0.1:%s' % get_core_args().port] process_args = {'stream': None} profile = MozProfile(profile=profile_path, preferences=Settings.default_fx_prefs) if OSHelper.is_windows(): process = subprocess.Popen([ fx_path, '-no-remote', '-new-tab', args, '--wait-for-browser', '-foreground', '-profile', profile.profile ], shell=False) else: fx_runner = FirefoxRunner(binary=fx_path, profile=profile, cmdargs=args, process_args=process_args) fx_runner.start() server = LocalWebServer(get_core_args().workdir, get_core_args().port) server.stop() time.sleep(Settings.DEFAULT_UI_DELAY) if OSHelper.is_mac(): type(text='q', modifier=KeyModifier.CMD) elif OSHelper.is_windows(): type(text='w', modifier=[KeyModifier.CTRL, KeyModifier.SHIFT]) else: type(text='q', modifier=KeyModifier.CTRL) if OSHelper.is_windows(): if process.pid is not None: try: logger.debug('Closing Firefox process ID: %s' % process.pid) process = psutil.Process(process.pid) for proc in process.children(recursive=True): proc.kill() process.kill() except psutil.NoSuchProcess: pass else: try: fx_runner.stop() except Exception as e: logger.debug('Error stopping fx_runner') logger.debug(e) return server.result
def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({"marionette.enabled": True, "marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False}) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences({"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command(self.binary, self.binary_args if self.binary_args else [] + [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
def run(self): ''' Starts Firefox thread with Marionette turned on. ''' self.profile = FirefoxProfile() self.profile.set_preferences({"marionette.defaultPrefs.enabled" : True, "marionette.defaultPrefs.port": 2828, "browser.startup.page": 0, "browser.startup.homepage": "about:blank", }) self.runner = FirefoxRunner(profile = self.profile, binary = self.binary, kp_kwargs = {'processOutputLine' : [self.logger]}) self.runner.start() self._firefoxRunningEvent.set() self.runner.wait()
# For VC12+, make sure we can find the right bitness of pgort1x0.dll if not substs.get('HAVE_64BIT_BUILD'): for e in ('VS140COMNTOOLS', 'VS120COMNTOOLS'): if e not in env: continue vcdir = os.path.abspath(os.path.join(env[e], '../../VC/bin')) if os.path.exists(vcdir): env['PATH'] = '%s;%s' % (vcdir, env['PATH']) break # Run Firefox a first time to initialize its profile runner = FirefoxRunner(profile=profile, binary=build.get_binary_path( where="staged-package"), cmdargs=['javascript:Quitter.quit()'], env=env) runner.start() runner.wait() jarlog = os.getenv("JARLOG_FILE") if jarlog: env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog) print "jarlog: %s" % env["MOZ_JAR_LOG_FILE"] cmdargs = ["http://localhost:%d/index.html" % PORT] runner = FirefoxRunner(profile=profile, binary=build.get_binary_path( where="staged-package"), cmdargs=cmdargs,
def valgrind_test(self, suppressions): from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath from six import string_types from valgrind.output_handler import OutputHandler build_dir = os.path.join(self.topsrcdir, "build") # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo")) httpd.start(block=False) with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile profile_data_dir = os.path.join(self.topsrcdir, "testing", "profiles") with open(os.path.join(profile_data_dir, "profiles.json"), "r") as fh: base_profiles = json.load(fh)["valgrind"] prefpaths = [ os.path.join(profile_data_dir, profile, "user.js") for profile in base_profiles ] prefs = {} for path in prefpaths: prefs.update(Preferences.read_prefs(path)) interpolation = { "server": "%s:%d" % httpd.httpd.server_address, } for k, v in prefs.items(): if isinstance(v, string_types): v = v.format(**interpolation) prefs[k] = Preferences.cast(v) quitter = os.path.join(self.topsrcdir, "tools", "quitter", "*****@*****.**") locations = ServerLocations() locations.add_host(host="127.0.0.1", port=httpd.httpd.server_port, options="primary") profile = FirefoxProfile( profile=profilePath, preferences=prefs, addons=[quitter], locations=locations, ) firefox_args = [httpd.get_url()] env = os.environ.copy() env["G_SLICE"] = "always-malloc" env["MOZ_CC_RUN_DURING_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" env["XPCOM_DEBUG_BREAK"] = "warn" outputHandler = OutputHandler(self.log) kp_kwargs = { "processOutputLine": [outputHandler], "universal_newlines": True, } valgrind = "valgrind" if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, "--sym-offsets=yes", "--smc-check=all-non-file", "--vex-iropt-register-updates=allregs-at-mem-access", "--gen-suppressions=all", "--num-callers=36", "--leak-check=full", "--show-possibly-lost=no", "--track-origins=yes", "--trace-children=yes", "-v", # Enable verbosity to get the list of used suppressions # Avoid excessive delays in the presence of spinlocks. # See bug 1309851. "--fair-sched=yes", # Keep debuginfo after library unmap. See bug 1382280. "--keep-debuginfo=yes", # Reduce noise level on rustc and/or LLVM compiled code. # See bug 1365915 "--expensive-definedness-checks=yes", # Compensate for the compiler inlining `new` but not `delete` # or vice versa. "--show-mismatched-frees=no", ] for s in suppressions: valgrind_args.append("--suppressions=" + s) supps_dir = os.path.join(build_dir, "valgrind") supps_file1 = os.path.join(supps_dir, "cross-architecture.sup") valgrind_args.append("--suppressions=" + supps_file1) if mozinfo.os == "linux": machtype = { "x86_64": "x86_64-pc-linux-gnu", "x86": "i386-pc-linux-gnu", }.get(mozinfo.processor) if machtype: supps_file2 = os.path.join(supps_dir, machtype + ".sup") if os.path.isfile(supps_file2): valgrind_args.append("--suppressions=" + supps_file2) exitcode = None timeout = 1800 binary_not_found_exception = None try: runner = FirefoxRunner( profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs, ) runner.start(debug_args=valgrind_args) exitcode = runner.wait(timeout=timeout) except BinaryNotFoundException as e: binary_not_found_exception = e finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange self.log( logging.ERROR, "valgrind-fail-parsing", { "errs": errs, "supps": supps }, "TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors " "seen, but {supps} generated suppressions seen", ) elif errs == 0: status = 0 self.log( logging.INFO, "valgrind-pass", {}, "TEST-PASS | valgrind-test | valgrind found no errors", ) else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. if binary_not_found_exception: status = 2 # turns the TBPL job red self.log( logging.ERROR, "valgrind-fail-errors", {"error": str(binary_not_found_exception)}, "TEST-UNEXPECTED-FAIL | valgrind-test | {error}", ) self.log( logging.INFO, "valgrind-fail-errors", {"help": binary_not_found_exception.help()}, "{help}", ) elif exitcode is None: status = 2 # turns the TBPL job red self.log( logging.ERROR, "valgrind-fail-timeout", {"timeout": timeout}, "TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out " "(reached {timeout} second limit)", ) elif exitcode != 0: status = 2 # turns the TBPL job red self.log( logging.ERROR, "valgrind-fail-errors", {"exitcode": exitcode}, "TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code " "from Valgrind: {exitcode}", ) httpd.stop() return status
preferences=prefs, addons=[os.path.join(build.distdir, 'xpi-stage', 'quitter')], locations=locations) env = os.environ.copy() env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["XPCOM_DEBUG_BREAK"] = "warn" # For VC12, make sure we can find the right bitness of pgort120.dll if "VS120COMNTOOLS" in env and not substs["HAVE_64BIT_OS"]: vc12dir = os.path.abspath(os.path.join(env["VS120COMNTOOLS"], "../../VC/bin")) if os.path.exists(vc12dir): env["PATH"] = vc12dir + ";" + env["PATH"] jarlog = os.getenv("JARLOG_FILE") if jarlog: env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog) print "jarlog: %s" % env["MOZ_JAR_LOG_FILE"] cmdargs = ["http://localhost:%d/index.html" % PORT] runner = FirefoxRunner(profile=profile, binary=build.get_binary_path(where="staged-package"), cmdargs=cmdargs, env=env) runner.start(debug_args=debug_args, interactive=interactive) runner.wait() httpd.stop() finally: shutil.rmtree(profilePath)
class B2GDesktopReftest(RefTest): marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert (self.marionette.wait_for_port()) self.marionette.start_session() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, test_path, options): reftestlist = self.getManifestPath(test_path) if not reftestlist.startswith('file://'): reftestlist = 'file://%s' % reftestlist self.profile = self.create_profile(options, reftestlist, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line( options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status def create_profile(self, options, reftestlist, profile_to_clone=None): profile = RefTest.createReftestProfile( self, options, reftestlist, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False prefs[ "b2g.system_startup_url"] = "app://test-container.gaiamobile.org/index.html" prefs[ "b2g.system_manifest_url"] = "app://test-container.gaiamobile.org/manifest.webapp" prefs["browser.tabs.remote"] = False prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs[ "network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False prefs["reftest.uri"] = "%s" % reftestlist # Set a future policy version to avoid the telemetry prompt. prefs["toolkit.telemetry.prompted"] = 999 prefs["toolkit.telemetry.notifiedOptOut"] = 999 # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) return cmd, args def _on_output(self, line): print(line) # TODO use structured logging if "TEST-START" in line and "|" in line: self.last_test = line.split("|")[1].strip() def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" log.testFail(msg % (self.last_test, self.timeout)) # kill process to get a stack self.runner.stop(sig=signal.SIGABRT)
class FirefoxBrowser(Browser): used_ports = set() init_timeout = 60 shutdown_timeout = 60 def __init__(self, logger, binary, prefs_root, test_type, extra_prefs=None, debug_info=None, symbols_path=None, stackwalk_binary=None, certutil_binary=None, ca_certificate_path=None, e10s=False, stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False, stylo_threads=1, chaos_mode_flags=None): Browser.__init__(self, logger) self.binary = binary self.prefs_root = prefs_root self.test_type = test_type self.extra_prefs = extra_prefs self.marionette_port = None self.runner = None self.debug_info = debug_info self.profile = None self.symbols_path = symbols_path self.stackwalk_binary = stackwalk_binary self.ca_certificate_path = ca_certificate_path self.certutil_binary = certutil_binary self.e10s = e10s self.binary_args = binary_args if stackfix_dir: self.stack_fixer = get_stack_fixer_function( stackfix_dir, self.symbols_path) else: self.stack_fixer = None if timeout_multiplier: self.init_timeout = self.init_timeout * timeout_multiplier self.leak_report_file = None self.leak_check = leak_check self.stylo_threads = stylo_threads self.chaos_mode_flags = chaos_mode_flags def settings(self, test): return {"check_leaks": self.leak_check and not test.leaks} def start(self, **kwargs): if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) locations = ServerLocations( filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({ "marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False, "dom.send_after_paint_to_content": True, "network.preload": True }) if self.e10s: self.profile.set_preferences( {"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences( {"layout.interruptible-reflow.enabled": False}) if self.leak_check and kwargs.get("check_leaks", True): self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks.log") if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences( {"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command( self.binary, self.binary_args if self.binary_args else [] + [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner( profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started") def load_prefs(self): prefs = Preferences() prefs_path = os.path.join(self.prefs_root, "prefs_general.js") if os.path.exists(prefs_path): prefs.add(Preferences.read_prefs(prefs_path)) else: self.logger.warning("Failed to find base prefs file in %s" % prefs_path) # Add any custom preferences prefs.add(self.extra_prefs, cast=True) return prefs() def stop(self, force=False): if self.runner is not None and self.runner.is_running(): try: # For Firefox we assume that stopping the runner prompts the # browser to shut down. This allows the leak log to be written for clean, stop_f in [ (True, lambda: self.runner.wait(self.shutdown_timeout)), (False, lambda: self.runner.stop(signal.SIGTERM)), (False, lambda: self.runner.stop(signal.SIGKILL)) ]: if not force or not clean: retcode = stop_f() if retcode is not None: self.logger.info( "Browser exited with return code %s" % retcode) break except OSError: # This can happen on Windows if the process is already dead pass self.logger.debug("stopped") def process_leaks(self): self.logger.debug("PROCESS LEAKS %s" % self.leak_report_file) if self.leak_report_file is None: return mozleak.process_leak_log( self.leak_report_file, leak_thresholds={ "default": 0, "tab": 10000, # See dependencies of bug 1051230. # GMP rarely gets a log, but when it does, it leaks a little. "geckomediaplugin": 20000, }, ignore_missing_leaks=["geckomediaplugin"], log=self.logger, stack_fixer=self.stack_fixer) def pid(self): if self.runner.process_handler is None: return None try: return self.runner.process_handler.pid except AttributeError: return None def on_output(self, line): """Write a line of output from the firefox process to the log""" data = line.decode("utf8", "replace") if self.stack_fixer: data = self.stack_fixer(data) self.logger.process_output(self.pid(), data, command=" ".join(self.runner.command)) def is_alive(self): if self.runner: return self.runner.is_running() return False def cleanup(self): self.stop() self.process_leaks() def executor_browser(self): assert self.marionette_port is not None return ExecutorBrowser, {"marionette_port": self.marionette_port} def check_for_crashes(self): dump_dir = os.path.join(self.profile.profile, "minidumps") return bool( mozcrash.check_for_crashes(dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, quiet=True)) def log_crash(self, process, test): dump_dir = os.path.join(self.profile.profile, "minidumps") mozcrash.log_crashes(self.logger, dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, process=process, test=test) def setup_ssl(self): """Create a certificate database to use in the test profile. This is configured to trust the CA Certificate that has signed the web-platform.test server certificate.""" if self.certutil_binary is None: self.logger.info( "--certutil-binary not supplied; Firefox will not check certificates" ) return self.logger.info("Setting up ssl") # Make sure the certutil libraries from the source tree are loaded when using a # local copy of certutil # TODO: Maybe only set this if certutil won't launch? env = os.environ.copy() certutil_dir = os.path.dirname(self.binary) if mozinfo.isMac: env_var = "DYLD_LIBRARY_PATH" elif mozinfo.isUnix: env_var = "LD_LIBRARY_PATH" else: env_var = "PATH" env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]]) if env_var in env else certutil_dir).encode( sys.getfilesystemencoding() or 'utf-8', 'replace') def certutil(*args): cmd = [self.certutil_binary] + list(args) self.logger.process_output( "certutil", subprocess.check_output(cmd, env=env, stderr=subprocess.STDOUT), " ".join(cmd)) pw_path = os.path.join(self.profile.profile, ".crtdbpw") with open(pw_path, "w") as f: # Use empty password for certificate db f.write("\n") cert_db_path = self.profile.profile # Create a new certificate db certutil("-N", "-d", cert_db_path, "-f", pw_path) # Add the CA certificate to the database and mark as trusted to issue server certs certutil("-A", "-d", cert_db_path, "-f", pw_path, "-t", "CT,,", "-n", "web-platform-tests", "-i", self.ca_certificate_path) # List all certs in the database certutil("-L", "-d", cert_db_path)
env["XPCOM_DEBUG_BREAK"] = "warn" # For VC12+, make sure we can find the right bitness of pgort1x0.dll if not substs.get('HAVE_64BIT_BUILD'): for e in ('VS140COMNTOOLS', 'VS120COMNTOOLS'): if e not in env: continue vcdir = os.path.abspath(os.path.join(env[e], '../../VC/bin')) if os.path.exists(vcdir): env['PATH'] = '%s;%s' % (vcdir, env['PATH']) break # Run Firefox a first time to initialize its profile runner = FirefoxRunner(profile=profile, binary=binary, cmdargs=['data:text/html,<script>Quitter.quit()</script>'], env=env) runner.start() ret = runner.wait() if ret: print("Firefox exited with code %d during profile initialization" % ret) httpd.stop() sys.exit(ret) jarlog = os.getenv("JARLOG_FILE") if jarlog: env["MOZ_JAR_LOG_FILE"] = os.path.abspath(jarlog) print("jarlog: %s" % env["MOZ_JAR_LOG_FILE"]) cmdargs = ["http://localhost:%d/index.html" % PORT]
def bisectRecurse(self, testcondition=None, args_for_condition=[]): #Recursively build, run, and prompt verdict = "" current_revision = captureStdout(self.hgPrefix + ["id", "-i"]) if self.remote: print "on current revision " + current_revision print "This would ask for a remote changeset, but it's not implemented yet." #TODO: #Remote bisection! #Step 1. Check if revision is in the archive #Step 2. If revision is not in the archive, set remote=False and continue (it will build and bisect that revision) #if not check_archived: # set remote false and continue #else: #Step 3. If the revision is in the archive, download it and its corresponding tests #STEP3 #1. Extract tests into some directory #2. Extract Nightly.app into "tests" #MozInstaller(src=, dest="", dest_app="Nightly.app") #3. run the following: #test_command = ['python', 'mochitest/runtests.py', '--appname=./Nightly.app/Contents/MacOS/firefox-bin', '--utility-path=bin', '--extra-profile-file=bin/plugins', '--certificate-path=certs', '--autorun', '--close-when-done', '--console-level=INFO', '--test-path=test_name'] #output = captureStdout(test_command, ignoreStderr=True) #set verdict based on output #python mochitest/runtests.py --appname=./Nightly.app/Contents/MacOS/firefox-bin --utility-path=bin --extra-profile-file=bin/plugins --certificate-path=certs --autorun --close-when-done --console-level=INFO --test-path=test_name #example test name: Harness_sanity/test_sanityException.html #Step 4. Run and run test to get verdict #Step 5. Set verdict elif self.tryPusher: try: caller = BuildCaller(host=self.tryhost, port=int(self.tryport), data=current_revision) print "Getting revision " + current_revision + "..." except: print "Failed to connect to trypusher. Make sure your settings are correct and that the trypusher server was started." exit() response = caller.getChangeset() print "Waiting on Mozilla Pulse for revision " + response + "..." url = caller.getURLResponse(response) print "the base is " + url_base(url) #Download it here #1. Download from url, extract to same place as tests #2. Run test or start browser. binary_path = os.path.join(self.binaryDir, url_base(url)) downloaded_binary = download_url(url, dest=str(binary_path)) MozInstaller(src=str(binary_path), dest=str(self.testDir), dest_app="Nightly.app") #now nightly is installed in if sys.platform == "darwin": binary_path = os.path.join(self.testDir, "Nightly.app") runner = FirefoxRunner.create( binary=os.path.join(binary_path, "Contents", "MacOS") + "/firefox-bin") elif sys.platform == "linux2": binary_path = os.path.join(self.testDir, "firefox") runner = FirefoxRunner.create(binary=binary_path) elif sys.platform == "win32" or sys.platform == "cygwin": binary_path = os.path.join(self.testDir, "firefox.exe") runner = FirefoxRunner.create(binary=binary_path) else: print "Your platform is not currently supported." quit() dest = runner.start() if not dest: print "Failed to start the downloaded binary" verdict == "skip" runner.wait() if verdict == "skip": pass elif testcondition != None: #Support condition scripts where arg0 is the directory with the binary and tests args_to_pass = [self.testDir] + args_for_condition if hasattr(testcondition, "init"): testcondition.init(args_to_pass) #TODO: refactor to use directories with revision numbers #8.2.11 - revision number can now be found in current_revision variable tmpdir = tempfile.mkdtemp() verdict = testcondition.interesting(args_to_pass, tmpdir) #Allow user to return true/false or bad/good if verdict != "bad" and verdict != "good": verdict = "bad" if verdict else "good" else: try: self.build() except Exception: print "This build failed!" verdict = "skip" if verdict == "skip": pass elif testcondition == None: #Not using a test, interactive bisect begin! self.run() else: #Using Jesse's idea: import any testing script and run it as the truth condition args_to_pass = [self.objdir] + args_for_condition if hasattr(testcondition, "init"): testcondition.init(args_to_pass) #TODO: refactor to use directories with revision numbers #8.2.11 - revision number can now be found in current_revision variable tmpdir = tempfile.mkdtemp() verdict = testcondition.interesting(args_to_pass, tmpdir) #Allow user to return true/false or bad/good if verdict != "bad" and verdict != "good": verdict = "bad" if verdict else "good" while verdict not in ["good", "bad", "skip"]: verdict = raw_input( "Was this commit good or bad? (type 'good', 'bad', or 'skip'): " ) if verdict == 'g': verdict = "good" if verdict == 'b': verdict = "bad" if verdict == 's': verdict = "skip" # do hg bisect --good, --bad, or --skip verdictCommand = self.hgPrefix + ["bisect", "--" + verdict] print " ".join(verdictCommand) retval = captureStdout(verdictCommand) string_to_parse = str(retval) print string_to_parse self.check_done(string_to_parse) if retval.startswith("Testing changeset"): print "\n" self.bisectRecurse(testcondition=testcondition, args_for_condition=args_for_condition)
def valgrind_test(self, suppressions): import json import re import sys import tempfile from mozbuild.base import MozbuildObject from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath build_dir = os.path.join(self.topsrcdir, "build") # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo")) httpd.start(block=False) with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile prefpath = os.path.join(self.topsrcdir, "testing", "profiles", "prefs_general.js") prefs = {} prefs.update(Preferences.read_prefs(prefpath)) interpolation = {"server": "%s:%d" % httpd.httpd.server_address, "OOP": "false"} prefs = json.loads(json.dumps(prefs) % interpolation) for pref in prefs: prefs[pref] = Preferences.cast(prefs[pref]) quitter = os.path.join(self.distdir, "xpi-stage", "quitter") locations = ServerLocations() locations.add_host(host="127.0.0.1", port=httpd.httpd.server_port, options="primary") profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations) firefox_args = [httpd.get_url()] env = os.environ.copy() env["G_SLICE"] = "always-malloc" env["XPCOM_CC_RUN_DURING_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["XPCOM_DEBUG_BREAK"] = "warn" class OutputHandler(object): def __init__(self): self.found_errors = False def __call__(self, line): print(line) m = re.match(r".*ERROR SUMMARY: [1-9]\d* errors from \d+ contexts", line) if m: self.found_errors = True outputHandler = OutputHandler() kp_kwargs = {"processOutputLine": [outputHandler]} valgrind = "valgrind" if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, "--smc-check=all-non-file", "--vex-iropt-register-updates=allregs-at-mem-access", "--gen-suppressions=all", "--num-callers=20", "--leak-check=full", "--show-possibly-lost=no", "--track-origins=yes", ] for s in suppressions: valgrind_args.append("--suppressions=" + s) supps_dir = os.path.join(build_dir, "valgrind") supps_file1 = os.path.join(supps_dir, "cross-architecture.sup") valgrind_args.append("--suppressions=" + supps_file1) # MACHTYPE is an odd bash-only environment variable that doesn't # show up in os.environ, so we have to get it another way. machtype = subprocess.check_output(["bash", "-c", "echo $MACHTYPE"]).rstrip() supps_file2 = os.path.join(supps_dir, machtype + ".sup") if os.path.isfile(supps_file2): valgrind_args.append("--suppressions=" + supps_file2) exitcode = None try: runner = FirefoxRunner( profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, kp_kwargs=kp_kwargs ) runner.start(debug_args=valgrind_args) exitcode = runner.wait() finally: if not outputHandler.found_errors: status = 0 print("TEST-PASS | valgrind-test | valgrind found no errors") else: status = 1 # turns the TBPL job orange print("TEST-UNEXPECTED-FAIL | valgrind-test | valgrind found errors") if exitcode != 0: status = 2 # turns the TBPL job red print("TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind") httpd.stop() return status
def start(self, group_metadata=None, **kwargs): if group_metadata is None: group_metadata = {} if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) if self.asan: print "Setting up LSAN" self.lsan_handler = mozleak.LSANLeaks( self.logger, scope=group_metadata.get("scope", "/"), allowed=self.lsan_allowed, maxNumRecordedFrames=self.lsan_max_stack_depth) env = test_environment(xrePath=os.path.dirname(self.binary), debugger=self.debug_info is not None, log=self.logger, lsanPath=self.prefs_root) env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) if self.headless: env["MOZ_HEADLESS"] = "1" preferences = self.load_prefs() self.profile = FirefoxProfile(preferences=preferences) self.profile.set_preferences({ "marionette.port": self.marionette_port, "network.dns.localDomains": ",".join(self.config.domains_set), "dom.file.createInChild": True, # TODO: Remove preferences once Firefox 64 is stable (Bug 905404) "network.proxy.type": 0, "places.history.enabled": False, "network.preload": True, }) if self.e10s: self.profile.set_preferences( {"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences( {"layout.interruptible-reflow.enabled": False}) if self.leak_check: self.leak_report_file = os.path.join( self.profile.profile, "runtests_leaks_%s.log" % os.getpid()) if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences( {"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"] debug_args, cmd = browser_command(self.binary, args, self.debug_info) self.runner = FirefoxRunner( profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
class FirefoxBrowser(Browser): used_ports = set() def __init__(self, logger, binary, prefs_root, debug_args=None, interactive=None, symbols_path=None, stackwalk_binary=None): Browser.__init__(self, logger) self.binary = binary self.prefs_root = prefs_root self.marionette_port = None self.used_ports.add(self.marionette_port) self.runner = None self.debug_args = debug_args self.interactive = interactive self.profile = None self.symbols_path = symbols_path self.stackwalk_binary = stackwalk_binary def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() ports = {"http": "8000", "https": "8443", "ws": "8888"} self.profile = FirefoxProfile(locations=locations, proxy=ports, preferences=preferences) self.profile.set_preferences({"marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False}) self.runner = FirefoxRunner(profile=self.profile, binary=self.binary, cmdargs=[cmd_arg("marionette"), "about:blank"], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=self.debug_args, interactive=self.interactive) self.logger.debug("Firefox Started") def load_prefs(self): prefs_path = os.path.join(self.prefs_root, "prefs_general.js") if os.path.exists(prefs_path): preferences = Preferences.read_prefs(prefs_path) else: self.logger.warning("Failed to find base prefs file in %s" % prefs_path) preferences = [] return preferences def stop(self): self.logger.debug("Stopping browser") if self.runner is not None: try: self.runner.stop() except OSError: # This can happen on Windows if the process is already dead pass def pid(self): if self.runner.process_handler is None: return None try: return self.runner.process_handler.pid except AttributeError: return None def on_output(self, line): """Write a line of output from the firefox process to the log""" self.logger.process_output(self.pid(), line.decode("utf8", "replace"), command=" ".join(self.runner.command)) def is_alive(self): if self.runner: return self.runner.is_running() return False def cleanup(self): self.stop() def executor_browser(self): assert self.marionette_port is not None return ExecutorBrowser, {"marionette_port": self.marionette_port} def log_crash(self, process, test): dump_dir = os.path.join(self.profile.profile, "minidumps") mozcrash.log_crashes(self.logger, dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, process=process, test=test)
def start(self, group_metadata=None, **kwargs): if group_metadata is None: group_metadata = {} if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) if self.asan: print "Setting up LSAN" self.lsan_handler = mozleak.LSANLeaks(self.logger, scope=group_metadata.get("scope", "/"), allowed=self.lsan_allowed, maxNumRecordedFrames=self.lsan_max_stack_depth) env = test_environment(xrePath=os.path.dirname(self.binary), debugger=self.debug_info is not None, log=self.logger, lsanPath=self.prefs_root) env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) if self.headless: env["MOZ_HEADLESS"] = "1" preferences = self.load_prefs() self.profile = FirefoxProfile(preferences=preferences) self.profile.set_preferences({ "marionette.port": self.marionette_port, "network.dns.localDomains": ",".join(self.config.domains_set), "dom.file.createInChild": True, # TODO: Remove preferences once Firefox 64 is stable (Bug 905404) "network.proxy.type": 0, "places.history.enabled": False, "network.preload": True, }) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences({"layout.interruptible-reflow.enabled": False}) if self.leak_check: self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks_%s.log" % os.getpid()) if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences({"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() args = self.binary_args[:] if self.binary_args else [] args += [cmd_arg("marionette"), "about:blank"] debug_args, cmd = browser_command(self.binary, args, self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
class TPSFirefoxRunner(object): PROCESS_TIMEOUT = 240 def __init__(self, binary): if binary is not None and ('http://' in binary or 'ftp://' in binary): self.url = binary self.binary = None else: self.url = None self.binary = binary self.runner = None self.installdir = None def __del__(self): if self.installdir: shutil.rmtree(self.installdir, True) def download_build(self, installdir='downloadedbuild', appname='firefox', macAppName='Minefield.app'): self.installdir = os.path.abspath(installdir) buildName = os.path.basename(self.url) pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)), buildName) # delete the build if it already exists if os.access(pathToBuild, os.F_OK): os.remove(pathToBuild) # download the build print "downloading build" download_url(self.url, pathToBuild) # install the build print "installing %s" % pathToBuild shutil.rmtree(self.installdir, True) MozInstaller(src=pathToBuild, dest=self.installdir, dest_app=macAppName) # remove the downloaded archive os.remove(pathToBuild) # calculate path to binary platform = get_platform() if platform['name'] == 'Mac': binary = '%s/%s/Contents/MacOS/%s-bin' % (installdir, macAppName, appname) else: binary = '%s/%s/%s%s' % (installdir, appname, appname, '.exe' if platform['name'] == 'Windows' else '') return binary 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() status = self.runner.process_handler.waitForFinish(timeout=timeout) return status
class B2GDesktopReftest(RefTest): build_type = "desktop" marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert(self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status def create_profile(self, options, manifests, profile_to_clone=None): profile = RefTest.createReftestProfile(self, options, manifests, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False if not self.build_type == "mulet": # FIXME: With Mulet we can't set this values since Gaia won't launch prefs["b2g.system_startup_url"] = \ "app://test-container.gaiamobile.org/index.html" prefs["b2g.system_manifest_url"] = \ "app://test-container.gaiamobile.org/manifest.webapp" # Make sure we disable system updates prefs["app.update.enabled"] = False prefs["app.update.url"] = "" prefs["app.update.url.override"] = "" # Disable webapp updates prefs["webapps.update.enabled"] = False # Disable tiles also prefs["browser.newtabpage.directory.source"] = "" prefs["browser.newtabpage.directory.ping"] = "" prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False # Set a future policy version to avoid the telemetry prompt. prefs["toolkit.telemetry.prompted"] = 999 prefs["toolkit.telemetry.notifiedOptOut"] = 999 # Disable periodic updates of service workers prefs["dom.serviceWorkers.periodic-updates.enabled"] = False # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) if self.build_type == "mulet": args += ['-chrome', 'chrome://b2g/content/shell.html'] return cmd, args def _on_output(self, line): sys.stdout.write("%s\n" % line) sys.stdout.flush() # TODO use structured logging if "TEST-START" in line and "|" in line: self.last_test = line.split("|")[1].strip() def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" log.testFail(msg % (self.last_test, self.timeout)) # kill process to get a stack self.runner.stop(sig=signal.SIGABRT)
class MuletReftest(RefTest): build_type = "mulet" marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert (self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line( options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status def create_profile(self, options, manifests, profile_to_clone=None): profile = RefTest.createReftestProfile( self, options, manifests, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False if not self.build_type == "mulet": # FIXME: With Mulet we can't set this values since Gaia won't launch prefs["b2g.system_startup_url"] = \ "app://test-container.gaiamobile.org/index.html" prefs["b2g.system_manifest_url"] = \ "app://test-container.gaiamobile.org/manifest.webapp" # Make sure we disable system updates prefs["app.update.enabled"] = False prefs["app.update.url"] = "" prefs["app.update.url.override"] = "" # Disable webapp updates prefs["webapps.update.enabled"] = False # Disable tiles also prefs["browser.newtabpage.directory.source"] = "" prefs["browser.newtabpage.directory.ping"] = "" prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs[ "network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False # Set a future policy version to avoid the telemetry prompt. prefs["toolkit.telemetry.prompted"] = 999 prefs["toolkit.telemetry.notifiedOptOut"] = 999 # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) if self.build_type == "mulet": args += ['-chrome', 'chrome://b2g/content/shell.html'] return cmd, args def _on_output(self, line): sys.stdout.write("%s\n" % line) sys.stdout.flush() # TODO use structured logging if "TEST-START" in line and "|" in line: self.last_test = line.split("|")[1].strip() def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" log.testFail(msg % (self.last_test, self.timeout)) # kill process to get a stack self.runner.stop(sig=signal.SIGABRT) def _unlockScreen(self): self.marionette.set_context(self.marionette.CONTEXT_CONTENT) self.marionette.import_script( os.path.abspath( os.path.join(__file__, os.path.pardir, "gaia_lock_screen.js"))) self.marionette.switch_to_frame() self.marionette.execute_async_script('GaiaLockScreen.unlock()') def _wait_for_homescreen(self, timeout): log.info("Waiting for home screen to load") Wait(self.marionette, timeout).until( expected.element_present(By.CSS_SELECTOR, '#homescreen[loading-state=false]'))
class B2GDesktopReftest(RefTest): def __init__(self, marionette): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette = marionette self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): assert(self.marionette.wait_for_port()) self.marionette.start_session() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, test_path, options): reftestlist = self.getManifestPath(test_path) if not reftestlist.startswith('file://'): reftestlist = 'file://%s' % reftestlist self.profile = self.create_profile(options, reftestlist, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) kp_kwargs = { 'processOutputLine': [self._on_output], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 log.info("%s | Running tests: start.", os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, symbols_path=options.symbolsPath, kp_kwargs=kp_kwargs) status = 0 try: self.runner.start(outputTimeout=self.timeout) log.info("%s | Application pid: %d", os.path.basename(__file__), self.runner.process_handler.pid) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: log.testFail("%s | application terminated with exit code %s", self.last_test, status) elif status < 0: log.info("%s | application killed with signal %s", self.last_test, -status) log.info("%s | Running tests: end.", os.path.basename(__file__)) return status def create_profile(self, options, reftestlist, profile_to_clone=None): profile = RefTest.createReftestProfile(self, options, reftestlist, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False prefs["browser.homescreenURL"] = "app://test-container.gaiamobile.org/index.html" prefs["browser.manifestURL"] = "app://test-container.gaiamobile.org/manifest.webapp" prefs["browser.tabs.remote"] = False prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False prefs["reftest.uri"] = "%s" % reftestlist # Set a future policy version to avoid the telemetry prompt. prefs["toolkit.telemetry.prompted"] = 999 prefs["toolkit.telemetry.notifiedOptOut"] = 999 # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False): cmd = os.path.abspath(app) args = ['-marionette'] if not ignore_window_size: args.extend(['--screen', '800x1000']) return cmd, args def _on_output(self, line): print(line) # TODO use structured logging if "TEST-START" in line and "|" in line: self.last_test = line.split("|")[1].strip() def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" log.testFail(msg % (self.last_test, self.timeout)) # kill process to get a stack self.runner.stop(sig=signal.SIGABRT)
class TPSFirefoxRunner(object): PROCESS_TIMEOUT = 240 def __init__(self, binary): if binary is not None and ('http://' in binary or 'ftp://' in binary): self.url = binary self.binary = None else: self.url = None self.binary = binary self.runner = None self.installdir = None def __del__(self): if self.installdir: shutil.rmtree(self.installdir, True) def download_url(self, url, dest=None): h = httplib2.Http() resp, content = h.request(url, "GET") if dest == None: dest = os.path.basename(url) local = open(dest, 'wb') local.write(content) local.close() return dest def download_build(self, installdir='downloadedbuild', appname='firefox'): self.installdir = os.path.abspath(installdir) buildName = os.path.basename(self.url) pathToBuild = os.path.join(os.path.dirname(os.path.abspath(__file__)), buildName) # delete the build if it already exists if os.access(pathToBuild, os.F_OK): os.remove(pathToBuild) # download the build print "downloading build" self.download_url(self.url, pathToBuild) # install the build print "installing %s" % pathToBuild shutil.rmtree(self.installdir, True) binary = mozinstall.install(src=pathToBuild, dest=self.installdir) # remove the downloaded archive os.remove(pathToBuild) return binary 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() status = self.runner.process_handler.waitForFinish(timeout=timeout) return status
class FirefoxBrowser(Browser): used_ports = set() init_timeout = 60 def __init__(self, logger, binary, prefs_root, debug_info=None, symbols_path=None, stackwalk_binary=None, certutil_binary=None, ca_certificate_path=None, e10s=False): Browser.__init__(self, logger) self.binary = binary self.prefs_root = prefs_root self.marionette_port = None self.runner = None self.debug_info = debug_info self.profile = None self.symbols_path = symbols_path self.stackwalk_binary = stackwalk_binary self.ca_certificate_path = ca_certificate_path self.certutil_binary = certutil_binary self.e10s = e10s def start(self): self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" locations = ServerLocations(filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({"marionette.defaultPrefs.enabled": True, "marionette.defaultPrefs.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False}) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences({"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command(self.binary, [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started") def load_prefs(self): prefs_path = os.path.join(self.prefs_root, "prefs_general.js") if os.path.exists(prefs_path): preferences = Preferences.read_prefs(prefs_path) else: self.logger.warning("Failed to find base prefs file in %s" % prefs_path) preferences = [] return preferences def stop(self): self.logger.debug("Stopping browser") if self.runner is not None: try: self.runner.stop() except OSError: # This can happen on Windows if the process is already dead pass def pid(self): if self.runner.process_handler is None: return None try: return self.runner.process_handler.pid except AttributeError: return None def on_output(self, line): """Write a line of output from the firefox process to the log""" self.logger.process_output(self.pid(), line.decode("utf8", "replace"), command=" ".join(self.runner.command)) def is_alive(self): if self.runner: return self.runner.is_running() return False def cleanup(self): self.stop() def executor_browser(self): assert self.marionette_port is not None return ExecutorBrowser, {"marionette_port": self.marionette_port} def log_crash(self, process, test): dump_dir = os.path.join(self.profile.profile, "minidumps") mozcrash.log_crashes(self.logger, dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, process=process, test=test) def setup_ssl(self): """Create a certificate database to use in the test profile. This is configured to trust the CA Certificate that has signed the web-platform.test server certificate.""" self.logger.info("Setting up ssl") # Make sure the certutil libraries from the source tree are loaded when using a # local copy of certutil # TODO: Maybe only set this if certutil won't launch? env = os.environ.copy() certutil_dir = os.path.dirname(self.binary) if mozinfo.isMac: env_var = "DYLD_LIBRARY_PATH" elif mozinfo.isUnix: env_var = "LD_LIBRARY_PATH" else: env_var = "PATH" env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]]) if env_var in env else certutil_dir).encode( sys.getfilesystemencoding() or 'utf-8', 'replace') def certutil(*args): cmd = [self.certutil_binary] + list(args) self.logger.process_output("certutil", subprocess.check_output(cmd, env=env, stderr=subprocess.STDOUT), " ".join(cmd)) pw_path = os.path.join(self.profile.profile, ".crtdbpw") with open(pw_path, "w") as f: # Use empty password for certificate db f.write("\n") cert_db_path = self.profile.profile # Create a new certificate db certutil("-N", "-d", cert_db_path, "-f", pw_path) # Add the CA certificate to the database and mark as trusted to issue server certs certutil("-A", "-d", cert_db_path, "-f", pw_path, "-t", "CT,,", "-n", "web-platform-tests", "-i", self.ca_certificate_path) # List all certs in the database certutil("-L", "-d", cert_db_path)
class MuletReftest(RefTest): build_type = "mulet" marionette = None def __init__(self, marionette_args): RefTest.__init__(self) self.last_test = os.path.basename(__file__) self.marionette_args = marionette_args self.profile = None self.runner = None self.test_script = os.path.join(here, 'b2g_start_script.js') self.timeout = None def run_marionette_script(self): self.marionette = Marionette(**self.marionette_args) assert(self.marionette.wait_for_port()) self.marionette.start_session() if self.build_type == "mulet": self._wait_for_homescreen(timeout=300) self._unlockScreen() self.marionette.set_context(self.marionette.CONTEXT_CHROME) if os.path.isfile(self.test_script): f = open(self.test_script, 'r') self.test_script = f.read() f.close() self.marionette.execute_script(self.test_script) def run_tests(self, tests, options): manifests = self.resolver.resolveManifests(options, tests) self.profile = self.create_profile(options, manifests, profile_to_clone=options.profile) env = self.buildBrowserEnv(options, self.profile.profile) self._populate_logger(options) outputHandler = OutputHandler(self.log, options.utilityPath, symbolsPath=options.symbolsPath) kp_kwargs = { 'processOutputLine': [outputHandler], 'onTimeout': [self._on_timeout], 'kill_on_timeout': False } if not options.debugger: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 self.timeout = options.timeout + 30.0 self.log.info("%s | Running tests: start." % os.path.basename(__file__)) cmd, args = self.build_command_line(options.app, ignore_window_size=options.ignoreWindowSize, browser_arg=options.browser_arg) self.runner = FirefoxRunner(profile=self.profile, binary=cmd, cmdargs=args, env=env, process_class=ProcessHandler, process_args=kp_kwargs, symbols_path=options.symbolsPath) status = 0 try: self.runner.start(outputTimeout=self.timeout) self.log.info("%s | Application pid: %d" % ( os.path.basename(__file__), self.runner.process_handler.pid)) # kick starts the reftest harness self.run_marionette_script() status = self.runner.wait() finally: self.runner.check_for_crashes(test_name=self.last_test) self.runner.cleanup() if status > 0: self.log.testFail("%s | application terminated with exit code %s" % ( self.last_test, status)) elif status < 0: self.log.info("%s | application killed with signal %s" % ( self.last_test, -status)) self.log.info("%s | Running tests: end." % os.path.basename(__file__)) return status def create_profile(self, options, manifests, profile_to_clone=None): profile = RefTest.createReftestProfile(self, options, manifests, profile_to_clone=profile_to_clone) prefs = {} # Turn off the locale picker screen prefs["browser.firstrun.show.localepicker"] = False if not self.build_type == "mulet": # FIXME: With Mulet we can't set this values since Gaia won't launch prefs["b2g.system_startup_url"] = \ "app://test-container.gaiamobile.org/index.html" prefs["b2g.system_manifest_url"] = \ "app://test-container.gaiamobile.org/manifest.webapp" # Make sure we disable system updates prefs["app.update.enabled"] = False prefs["app.update.url"] = "" # Disable webapp updates prefs["webapps.update.enabled"] = False # Disable tiles also prefs["browser.newtabpage.directory.source"] = "" prefs["browser.newtabpage.directory.ping"] = "" prefs["dom.ipc.tabs.disabled"] = False prefs["dom.mozBrowserFramesEnabled"] = True prefs["font.size.inflation.emPerLine"] = 0 prefs["font.size.inflation.minTwips"] = 0 prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" prefs["reftest.browser.iframe.enabled"] = False prefs["reftest.remote"] = False # Set the extra prefs. profile.set_preferences(prefs) return profile def build_command_line(self, app, ignore_window_size=False, browser_arg=None): cmd = os.path.abspath(app) args = ['-marionette'] if browser_arg: args += [browser_arg] if not ignore_window_size: args.extend(['--screen', '800x1000']) if self.build_type == "mulet": args += ['-chrome', 'chrome://b2g/content/shell.html'] return cmd, args def _on_timeout(self): msg = "%s | application timed out after %s seconds with no output" self.log.testFail(msg % (self.last_test, self.timeout)) self.log.error("Force-terminating active process(es)."); # kill process to get a stack self.runner.stop(sig=signal.SIGABRT) def _unlockScreen(self): self.marionette.set_context(self.marionette.CONTEXT_CONTENT) self.marionette.import_script(os.path.abspath( os.path.join(__file__, os.path.pardir, "gaia_lock_screen.js"))) self.marionette.switch_to_frame() self.marionette.execute_async_script('GaiaLockScreen.unlock()') def _wait_for_homescreen(self, timeout): self.log.info("Waiting for home screen to load") Wait(self.marionette, timeout).until(expected.element_present( By.CSS_SELECTOR, '#homescreen[loading-state=false]'))
def bisectRecurse(self, testcondition=None, args_for_condition=[]): #Recursively build, run, and prompt verdict = "" current_revision = captureStdout(self.hgPrefix+["id","-i"]) if self.remote: print "on current revision "+current_revision print "This would ask for a remote changeset, but it's not implemented yet." #TODO: #Remote bisection! #Step 1. Check if revision is in the archive #Step 2. If revision is not in the archive, set remote=False and continue (it will build and bisect that revision) #if not check_archived: # set remote false and continue #else: #Step 3. If the revision is in the archive, download it and its corresponding tests #STEP3 #1. Extract tests into some directory #2. Extract Nightly.app into "tests" #MozInstaller(src=, dest="", dest_app="Nightly.app") #3. run the following: #test_command = ['python', 'mochitest/runtests.py', '--appname=./Nightly.app/Contents/MacOS/firefox-bin', '--utility-path=bin', '--extra-profile-file=bin/plugins', '--certificate-path=certs', '--autorun', '--close-when-done', '--console-level=INFO', '--test-path=test_name'] #output = captureStdout(test_command, ignoreStderr=True) #set verdict based on output #python mochitest/runtests.py --appname=./Nightly.app/Contents/MacOS/firefox-bin --utility-path=bin --extra-profile-file=bin/plugins --certificate-path=certs --autorun --close-when-done --console-level=INFO --test-path=test_name #example test name: Harness_sanity/test_sanityException.html #Step 4. Run and run test to get verdict #Step 5. Set verdict elif self.tryPusher: try: caller = BuildCaller(host=self.tryhost, port=int(self.tryport), data=current_revision) print "Getting revision "+current_revision+"..." except: print "Failed to connect to trypusher. Make sure your settings are correct and that the trypusher server was started." exit() response = caller.getChangeset() print "Waiting on Mozilla Pulse for revision " + response + "..." url = caller.getURLResponse(response) print "the base is " +url_base(url) #Download it here #1. Download from url, extract to same place as tests #2. Run test or start browser. binary_path = os.path.join(self.binaryDir,url_base(url)) downloaded_binary = download_url(url, dest=str(binary_path)) MozInstaller(src=str(binary_path), dest=str(self.testDir), dest_app="Nightly.app") #now nightly is installed in if sys.platform == "darwin": binary_path = os.path.join(self.testDir,"Nightly.app") runner = FirefoxRunner(binary=os.path.join(binary_path,"Contents","MacOS")+"/firefox-bin") elif sys.platform == "linux2": binary_path = os.path.join(self.testDir,"firefox") runner = FirefoxRunner(binary=binary_path) elif sys.platform == "win32" or sys.platform == "cygwin": binary_path = os.path.join(self.testDir,"firefox.exe") runner = FirefoxRunner(binary=binary_path) else: print "Your platform is not currently supported." quit() dest = runner.start() if not dest: print "Failed to start the downloaded binary" verdict == "skip" runner.wait() if verdict == "skip": pass elif testcondition!=None: #Support condition scripts where arg0 is the directory with the binary and tests args_to_pass = [self.testDir] + args_for_condition if hasattr(testcondition, "init"): testcondition.init(args_to_pass) #TODO: refactor to use directories with revision numbers #8.2.11 - revision number can now be found in current_revision variable tmpdir = tempfile.mkdtemp() verdict = testcondition.interesting(args_to_pass,tmpdir) #Allow user to return true/false or bad/good if verdict != "bad" and verdict != "good": verdict = "bad" if verdict else "good" else: try: self.build() except Exception: print "This build failed!" verdict = "skip" if verdict == "skip": pass elif testcondition==None: #Not using a test, interactive bisect begin! self.run() else: #Using Jesse's idea: import any testing script and run it as the truth condition args_to_pass = [self.objdir] + args_for_condition if hasattr(testcondition, "init"): testcondition.init(args_to_pass) #TODO: refactor to use directories with revision numbers #8.2.11 - revision number can now be found in current_revision variable tmpdir = tempfile.mkdtemp() verdict = testcondition.interesting(args_to_pass,tmpdir) #Allow user to return true/false or bad/good if verdict != "bad" and verdict != "good": verdict = "bad" if verdict else "good" while verdict not in ["good", "bad", "skip"]: verdict = raw_input("Was this commit good or bad? (type 'good', 'bad', or 'skip'): ") if verdict == 'g': verdict = "good" if verdict == 'b': verdict = "bad" if verdict == 's': verdict = "skip" # do hg bisect --good, --bad, or --skip verdictCommand = self.hgPrefix+["bisect","--"+verdict] print " ".join(verdictCommand) retval = captureStdout(verdictCommand) string_to_parse = str(retval) print string_to_parse self.check_done(string_to_parse) if retval.startswith("Testing changeset"): print "\n" self.bisectRecurse(testcondition=testcondition, args_for_condition=args_for_condition)
def start(self, **kwargs): if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) locations = ServerLocations( filename=os.path.join(here, "server-locations.txt")) preferences = self.load_prefs() self.profile = FirefoxProfile(locations=locations, preferences=preferences) self.profile.set_preferences({ "marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(hostnames), "network.proxy.type": 0, "places.history.enabled": False, "dom.send_after_paint_to_content": True, "network.preload": True }) if self.e10s: self.profile.set_preferences( {"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences( {"layout.interruptible-reflow.enabled": False}) if self.leak_check and kwargs.get("check_leaks", True): self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks.log") if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences( {"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command( self.binary, self.binary_args if self.binary_args else [] + [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner( profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started")
class FirefoxBrowser(Browser): used_ports = set() init_timeout = 60 shutdown_timeout = 60 def __init__(self, logger, binary, prefs_root, test_type, extra_prefs=None, debug_info=None, symbols_path=None, stackwalk_binary=None, certutil_binary=None, ca_certificate_path=None, e10s=False, stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False, stylo_threads=1, chaos_mode_flags=None, config=None): Browser.__init__(self, logger) self.binary = binary self.prefs_root = prefs_root self.test_type = test_type self.extra_prefs = extra_prefs self.marionette_port = None self.runner = None self.debug_info = debug_info self.profile = None self.symbols_path = symbols_path self.stackwalk_binary = stackwalk_binary self.ca_certificate_path = ca_certificate_path self.certutil_binary = certutil_binary self.e10s = e10s self.binary_args = binary_args self.config = config if stackfix_dir: self.stack_fixer = get_stack_fixer_function(stackfix_dir, self.symbols_path) else: self.stack_fixer = None if timeout_multiplier: self.init_timeout = self.init_timeout * timeout_multiplier self.leak_report_file = None self.leak_check = leak_check self.stylo_threads = stylo_threads self.chaos_mode_flags = chaos_mode_flags def settings(self, test): return {"check_leaks": self.leak_check and not test.leaks} def start(self, **kwargs): if self.marionette_port is None: self.marionette_port = get_free_port(2828, exclude=self.used_ports) self.used_ports.add(self.marionette_port) env = os.environ.copy() env["MOZ_CRASHREPORTER"] = "1" env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1" env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1" env["STYLO_THREADS"] = str(self.stylo_threads) if self.chaos_mode_flags is not None: env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags) preferences = self.load_prefs() self.profile = FirefoxProfile(preferences=preferences) self.profile.set_preferences({"marionette.port": self.marionette_port, "dom.disable_open_during_load": False, "network.dns.localDomains": ",".join(self.config.domains_set), "network.proxy.type": 0, "places.history.enabled": False, "dom.send_after_paint_to_content": True, "network.preload": True}) if self.e10s: self.profile.set_preferences({"browser.tabs.remote.autostart": True}) if self.test_type == "reftest": self.profile.set_preferences({"layout.interruptible-reflow.enabled": False}) if self.leak_check and kwargs.get("check_leaks", True): self.leak_report_file = os.path.join(self.profile.profile, "runtests_leaks.log") if os.path.exists(self.leak_report_file): os.remove(self.leak_report_file) env["XPCOM_MEM_BLOAT_LOG"] = self.leak_report_file else: self.leak_report_file = None # Bug 1262954: winxp + e10s, disable hwaccel if (self.e10s and platform.system() in ("Windows", "Microsoft") and '5.1' in platform.version()): self.profile.set_preferences({"layers.acceleration.disabled": True}) if self.ca_certificate_path is not None: self.setup_ssl() debug_args, cmd = browser_command(self.binary, self.binary_args if self.binary_args else [] + [cmd_arg("marionette"), "about:blank"], self.debug_info) self.runner = FirefoxRunner(profile=self.profile, binary=cmd[0], cmdargs=cmd[1:], env=env, process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) self.logger.debug("Starting Firefox") self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.logger.debug("Firefox Started") def load_prefs(self): prefs = Preferences() pref_paths = [] prefs_general = os.path.join(self.prefs_root, 'prefs_general.js') if os.path.isfile(prefs_general): # Old preference file used in Firefox 60 and earlier (remove when no longer supported) pref_paths.append(prefs_general) profiles = os.path.join(self.prefs_root, 'profiles.json') if os.path.isfile(profiles): with open(profiles, 'r') as fh: for name in json.load(fh)['web-platform-tests']: pref_paths.append(os.path.join(self.prefs_root, name, 'user.js')) for path in pref_paths: if os.path.exists(path): prefs.add(Preferences.read_prefs(path)) else: self.logger.warning("Failed to find base prefs file in %s" % path) # Add any custom preferences prefs.add(self.extra_prefs, cast=True) return prefs() def stop(self, force=False): if self.runner is not None and self.runner.is_running(): try: # For Firefox we assume that stopping the runner prompts the # browser to shut down. This allows the leak log to be written for clean, stop_f in [(True, lambda: self.runner.wait(self.shutdown_timeout)), (False, lambda: self.runner.stop(signal.SIGTERM)), (False, lambda: self.runner.stop(signal.SIGKILL))]: if not force or not clean: retcode = stop_f() if retcode is not None: self.logger.info("Browser exited with return code %s" % retcode) break except OSError: # This can happen on Windows if the process is already dead pass self.logger.debug("stopped") def process_leaks(self): self.logger.debug("PROCESS LEAKS %s" % self.leak_report_file) if self.leak_report_file is None: return mozleak.process_leak_log( self.leak_report_file, leak_thresholds={ "default": 0, "tab": 10000, # See dependencies of bug 1051230. # GMP rarely gets a log, but when it does, it leaks a little. "geckomediaplugin": 20000, }, ignore_missing_leaks=["geckomediaplugin"], log=self.logger, stack_fixer=self.stack_fixer ) def pid(self): if self.runner.process_handler is None: return None try: return self.runner.process_handler.pid except AttributeError: return None def on_output(self, line): """Write a line of output from the firefox process to the log""" if "GLib-GObject-CRITICAL" in line: return if line: data = line.decode("utf8", "replace") if self.stack_fixer: data = self.stack_fixer(data) self.logger.process_output(self.pid(), data, command=" ".join(self.runner.command)) def is_alive(self): if self.runner: return self.runner.is_running() return False def cleanup(self): self.stop() self.process_leaks() def executor_browser(self): assert self.marionette_port is not None return ExecutorBrowser, {"marionette_port": self.marionette_port} def check_for_crashes(self): dump_dir = os.path.join(self.profile.profile, "minidumps") return bool(mozcrash.check_for_crashes(dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, quiet=True)) def log_crash(self, process, test): dump_dir = os.path.join(self.profile.profile, "minidumps") mozcrash.log_crashes(self.logger, dump_dir, symbols_path=self.symbols_path, stackwalk_binary=self.stackwalk_binary, process=process, test=test) def setup_ssl(self): """Create a certificate database to use in the test profile. This is configured to trust the CA Certificate that has signed the web-platform.test server certificate.""" if self.certutil_binary is None: self.logger.info("--certutil-binary not supplied; Firefox will not check certificates") return self.logger.info("Setting up ssl") # Make sure the certutil libraries from the source tree are loaded when using a # local copy of certutil # TODO: Maybe only set this if certutil won't launch? env = os.environ.copy() certutil_dir = os.path.dirname(self.binary) if mozinfo.isMac: env_var = "DYLD_LIBRARY_PATH" elif mozinfo.isUnix: env_var = "LD_LIBRARY_PATH" else: env_var = "PATH" env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]]) if env_var in env else certutil_dir).encode( sys.getfilesystemencoding() or 'utf-8', 'replace') def certutil(*args): cmd = [self.certutil_binary] + list(args) self.logger.process_output("certutil", subprocess.check_output(cmd, env=env, stderr=subprocess.STDOUT), " ".join(cmd)) pw_path = os.path.join(self.profile.profile, ".crtdbpw") with open(pw_path, "w") as f: # Use empty password for certificate db f.write("\n") cert_db_path = self.profile.profile # Create a new certificate db certutil("-N", "-d", cert_db_path, "-f", pw_path) # Add the CA certificate to the database and mark as trusted to issue server certs certutil("-A", "-d", cert_db_path, "-f", pw_path, "-t", "CT,,", "-n", "web-platform-tests", "-i", self.ca_certificate_path) # List all certs in the database certutil("-L", "-d", cert_db_path)
def valgrind_test(self, suppressions): import json import sys import tempfile from mozbuild.base import MozbuildObject from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath from valgrind.output_handler import OutputHandler build_dir = os.path.join(self.topsrcdir, "build") # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, "pgo")) httpd.start(block=False) with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile prefpath = os.path.join(self.topsrcdir, "testing", "profiles", "prefs_general.js") prefs = {} prefs.update(Preferences.read_prefs(prefpath)) interpolation = {"server": "%s:%d" % httpd.httpd.server_address, "OOP": "false"} prefs = json.loads(json.dumps(prefs) % interpolation) for pref in prefs: prefs[pref] = Preferences.cast(prefs[pref]) quitter = os.path.join(self.topsrcdir, "tools", "quitter", "*****@*****.**") locations = ServerLocations() locations.add_host(host="127.0.0.1", port=httpd.httpd.server_port, options="primary") profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations) firefox_args = [httpd.get_url()] env = os.environ.copy() env["G_SLICE"] = "always-malloc" env["MOZ_CC_RUN_DURING_SHUTDOWN"] = "1" env["MOZ_CRASHREPORTER_NO_REPORT"] = "1" env["XPCOM_DEBUG_BREAK"] = "warn" env.update(self.extra_environment_variables) outputHandler = OutputHandler(self.log) kp_kwargs = {"processOutputLine": [outputHandler]} valgrind = "valgrind" if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, "--smc-check=all-non-file", "--vex-iropt-register-updates=allregs-at-mem-access", "--gen-suppressions=all", "--num-callers=36", "--leak-check=full", "--show-possibly-lost=no", "--track-origins=yes", "--trace-children=yes", "-v", # Enable verbosity to get the list of used suppressions ] for s in suppressions: valgrind_args.append("--suppressions=" + s) supps_dir = os.path.join(build_dir, "valgrind") supps_file1 = os.path.join(supps_dir, "cross-architecture.sup") valgrind_args.append("--suppressions=" + supps_file1) # MACHTYPE is an odd bash-only environment variable that doesn't # show up in os.environ, so we have to get it another way. machtype = subprocess.check_output(["bash", "-c", "echo $MACHTYPE"]).rstrip() supps_file2 = os.path.join(supps_dir, machtype + ".sup") if os.path.isfile(supps_file2): valgrind_args.append("--suppressions=" + supps_file2) exitcode = None timeout = 1800 try: runner = FirefoxRunner( profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs, ) runner.start(debug_args=valgrind_args) exitcode = runner.wait(timeout=timeout) finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange self.log( logging.ERROR, "valgrind-fail-parsing", {"errs": errs, "supps": supps}, "TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors seen, but {supps} generated suppressions seen", ) elif errs == 0: status = 0 self.log(logging.INFO, "valgrind-pass", {}, "TEST-PASS | valgrind-test | valgrind found no errors") else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. if exitcode == None: status = 2 # turns the TBPL job red self.log( logging.ERROR, "valgrind-fail-timeout", {"timeout": timeout}, "TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {timeout} second limit)", ) elif exitcode != 0: status = 2 # turns the TBPL job red self.log( logging.ERROR, "valgrind-fail-errors", {}, "TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind", ) httpd.stop() return status
def valgrind_test(self, suppressions): from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath from six import string_types from valgrind.output_handler import OutputHandler build_dir = os.path.join(self.topsrcdir, 'build') # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo')) httpd.start(block=False) with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile profile_data_dir = os.path.join( self.topsrcdir, 'testing', 'profiles') with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh: base_profiles = json.load(fh)['valgrind'] prefpaths = [os.path.join(profile_data_dir, profile, 'user.js') for profile in base_profiles] prefs = {} for path in prefpaths: prefs.update(Preferences.read_prefs(path)) interpolation = { 'server': '%s:%d' % httpd.httpd.server_address, } for k, v in prefs.items(): if isinstance(v, string_types): v = v.format(**interpolation) prefs[k] = Preferences.cast(v) quitter = os.path.join( self.topsrcdir, 'tools', 'quitter', '*****@*****.**') locations = ServerLocations() locations.add_host(host='127.0.0.1', port=httpd.httpd.server_port, options='primary') profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations) firefox_args = [httpd.get_url()] env = os.environ.copy() env['G_SLICE'] = 'always-malloc' env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1' env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' env['XPCOM_DEBUG_BREAK'] = 'warn' env.update(self.extra_environment_variables) outputHandler = OutputHandler(self.log) kp_kwargs = {'processOutputLine': [outputHandler]} valgrind = 'valgrind' if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, '--smc-check=all-non-file', '--vex-iropt-register-updates=allregs-at-mem-access', '--gen-suppressions=all', '--num-callers=36', '--leak-check=full', '--show-possibly-lost=no', '--track-origins=yes', '--trace-children=yes', '-v', # Enable verbosity to get the list of used suppressions # Avoid excessive delays in the presence of spinlocks. # See bug 1309851. '--fair-sched=yes', # Keep debuginfo after library unmap. See bug 1382280. '--keep-debuginfo=yes', # Reduce noise level on rustc and/or LLVM compiled code. # See bug 1365915 '--expensive-definedness-checks=yes', ] for s in suppressions: valgrind_args.append('--suppressions=' + s) supps_dir = os.path.join(build_dir, 'valgrind') supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup') valgrind_args.append('--suppressions=' + supps_file1) if mozinfo.os == 'linux': machtype = { 'x86_64': 'x86_64-pc-linux-gnu', 'x86': 'i386-pc-linux-gnu', }.get(mozinfo.processor) if machtype: supps_file2 = os.path.join(supps_dir, machtype + '.sup') if os.path.isfile(supps_file2): valgrind_args.append('--suppressions=' + supps_file2) exitcode = None timeout = 1800 try: runner = FirefoxRunner(profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs) runner.start(debug_args=valgrind_args) exitcode = runner.wait(timeout=timeout) finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange self.log(logging.ERROR, 'valgrind-fail-parsing', {'errs': errs, 'supps': supps}, 'TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors ' 'seen, but {supps} generated suppressions seen') elif errs == 0: status = 0 self.log(logging.INFO, 'valgrind-pass', {}, 'TEST-PASS | valgrind-test | valgrind found no errors') else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. if exitcode is None: status = 2 # turns the TBPL job red self.log(logging.ERROR, 'valgrind-fail-timeout', {'timeout': timeout}, 'TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out ' '(reached {timeout} second limit)') elif exitcode != 0: status = 2 # turns the TBPL job red self.log(logging.ERROR, 'valgrind-fail-errors', {}, 'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code' 'from Valgrind') httpd.stop() return status
def valgrind_test(self, suppressions): import json import sys import tempfile from mozbuild.base import MozbuildObject from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath from valgrind.output_handler import OutputHandler build_dir = os.path.join(self.topsrcdir, 'build') # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo')) httpd.start(block=False) with TemporaryDirectory() as profilePath: #TODO: refactor this into mozprofile prefpath = os.path.join(self.topsrcdir, 'testing', 'profiles', 'prefs_general.js') prefs = {} prefs.update(Preferences.read_prefs(prefpath)) interpolation = { 'server': '%s:%d' % httpd.httpd.server_address, 'OOP': 'false'} prefs = json.loads(json.dumps(prefs) % interpolation) for pref in prefs: prefs[pref] = Preferences.cast(prefs[pref]) quitter = os.path.join(self.distdir, 'xpi-stage', 'quitter') locations = ServerLocations() locations.add_host(host='127.0.0.1', port=httpd.httpd.server_port, options='primary') profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations) firefox_args = [httpd.get_url()] env = os.environ.copy() env['G_SLICE'] = 'always-malloc' env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1' env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' env['XPCOM_DEBUG_BREAK'] = 'warn' env.update(self.extra_environment_variables) outputHandler = OutputHandler() kp_kwargs = {'processOutputLine': [outputHandler]} valgrind = 'valgrind' if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, '--smc-check=all-non-file', '--vex-iropt-register-updates=allregs-at-mem-access', '--gen-suppressions=all', '--num-callers=36', '--leak-check=full', '--show-possibly-lost=no', '--track-origins=yes', '--trace-children=yes', # The gstreamer plugin scanner can run as part of executing # firefox, but is an external program. In some weird cases, # valgrind finds errors while executing __libc_freeres when # it runs, but those are not relevant, as it's related to # executing third party code. So don't trace # gst-plugin-scanner. '--trace-children-skip=*/gst-plugin-scanner', '-v', # Enable verbosity to get the list of used suppressions ] for s in suppressions: valgrind_args.append('--suppressions=' + s) supps_dir = os.path.join(build_dir, 'valgrind') supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup') valgrind_args.append('--suppressions=' + supps_file1) # MACHTYPE is an odd bash-only environment variable that doesn't # show up in os.environ, so we have to get it another way. machtype = subprocess.check_output(['bash', '-c', 'echo $MACHTYPE']).rstrip() supps_file2 = os.path.join(supps_dir, machtype + '.sup') if os.path.isfile(supps_file2): valgrind_args.append('--suppressions=' + supps_file2) exitcode = None timeout = 1100 try: runner = FirefoxRunner(profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs) runner.start(debug_args=valgrind_args) # This timeout is slightly less than the no-output timeout on # TBPL, so we'll timeout here first and give an informative # message. exitcode = runner.wait(timeout=timeout) finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange print('TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {} errors seen, but {} generated suppressions seen'.format(errs, supps)) elif errs == 0: status = 0 print('TEST-PASS | valgrind-test | valgrind found no errors') else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. if exitcode == None: status = 2 # turns the TBPL job red print('TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out (reached {} second limit)'.format(timeout)) elif exitcode != 0: status = 2 # turns the TBPL job red print('TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code from Valgrind') httpd.stop() return status
def valgrind_test(self, suppressions): from mozfile import TemporaryDirectory from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences from mozprofile.permissions import ServerLocations from mozrunner import FirefoxRunner from mozrunner.utils import findInPath from six import string_types from valgrind.output_handler import OutputHandler build_dir = os.path.join(self.topsrcdir, 'build') # XXX: currently we just use the PGO inputs for Valgrind runs. This may # change in the future. httpd = MozHttpd(docroot=os.path.join(build_dir, 'pgo')) httpd.start(block=False) with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile profile_data_dir = os.path.join(self.topsrcdir, 'testing', 'profiles') with open(os.path.join(profile_data_dir, 'profiles.json'), 'r') as fh: base_profiles = json.load(fh)['valgrind'] prefpaths = [ os.path.join(profile_data_dir, profile, 'user.js') for profile in base_profiles ] prefs = {} for path in prefpaths: prefs.update(Preferences.read_prefs(path)) interpolation = { 'server': '%s:%d' % httpd.httpd.server_address, } for k, v in prefs.items(): if isinstance(v, string_types): v = v.format(**interpolation) prefs[k] = Preferences.cast(v) quitter = os.path.join(self.topsrcdir, 'tools', 'quitter', '*****@*****.**') locations = ServerLocations() locations.add_host(host='127.0.0.1', port=httpd.httpd.server_port, options='primary') profile = FirefoxProfile(profile=profilePath, preferences=prefs, addons=[quitter], locations=locations) firefox_args = [httpd.get_url()] env = os.environ.copy() env['G_SLICE'] = 'always-malloc' env['MOZ_CC_RUN_DURING_SHUTDOWN'] = '1' env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' env['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] = '1' env['XPCOM_DEBUG_BREAK'] = 'warn' env.update(self.extra_environment_variables) outputHandler = OutputHandler(self.log) kp_kwargs = {'processOutputLine': [outputHandler]} valgrind = 'valgrind' if not os.path.exists(valgrind): valgrind = findInPath(valgrind) valgrind_args = [ valgrind, '--sym-offsets=yes', '--smc-check=all-non-file', '--vex-iropt-register-updates=allregs-at-mem-access', '--gen-suppressions=all', '--num-callers=36', '--leak-check=full', '--show-possibly-lost=no', '--track-origins=yes', '--trace-children=yes', '-v', # Enable verbosity to get the list of used suppressions # Avoid excessive delays in the presence of spinlocks. # See bug 1309851. '--fair-sched=yes', # Keep debuginfo after library unmap. See bug 1382280. '--keep-debuginfo=yes', # Reduce noise level on rustc and/or LLVM compiled code. # See bug 1365915 '--expensive-definedness-checks=yes', ] for s in suppressions: valgrind_args.append('--suppressions=' + s) supps_dir = os.path.join(build_dir, 'valgrind') supps_file1 = os.path.join(supps_dir, 'cross-architecture.sup') valgrind_args.append('--suppressions=' + supps_file1) if mozinfo.os == 'linux': machtype = { 'x86_64': 'x86_64-pc-linux-gnu', 'x86': 'i386-pc-linux-gnu', }.get(mozinfo.processor) if machtype: supps_file2 = os.path.join(supps_dir, machtype + '.sup') if os.path.isfile(supps_file2): valgrind_args.append('--suppressions=' + supps_file2) exitcode = None timeout = 1800 try: runner = FirefoxRunner(profile=profile, binary=self.get_binary_path(), cmdargs=firefox_args, env=env, process_args=kp_kwargs) runner.start(debug_args=valgrind_args) exitcode = runner.wait(timeout=timeout) finally: errs = outputHandler.error_count supps = outputHandler.suppression_count if errs != supps: status = 1 # turns the TBPL job orange self.log( logging.ERROR, 'valgrind-fail-parsing', { 'errs': errs, 'supps': supps }, 'TEST-UNEXPECTED-FAIL | valgrind-test | error parsing: {errs} errors ' 'seen, but {supps} generated suppressions seen') elif errs == 0: status = 0 self.log( logging.INFO, 'valgrind-pass', {}, 'TEST-PASS | valgrind-test | valgrind found no errors') else: status = 1 # turns the TBPL job orange # We've already printed details of the errors. if exitcode is None: status = 2 # turns the TBPL job red self.log( logging.ERROR, 'valgrind-fail-timeout', {'timeout': timeout}, 'TEST-UNEXPECTED-FAIL | valgrind-test | Valgrind timed out ' '(reached {timeout} second limit)') elif exitcode != 0: status = 2 # turns the TBPL job red self.log( logging.ERROR, 'valgrind-fail-errors', {'exitcode': exitcode}, 'TEST-UNEXPECTED-FAIL | valgrind-test | non-zero exit code ' 'from Valgrind: {exitcode}') httpd.stop() return status