def runSerialTests(self, testPath, options, cmdlineArgs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None try: reftestlist = self.getManifestPath(testPath) if cmdlineArgs == None: cmdlineArgs = ['-reftest', reftestlist] profile = self.createReftestProfile(options, reftestlist) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) log.info("REFTEST INFO | runreftest.py | Running tests: start.\n") status = self.runApp(profile, binary=options.app, cmdargs=cmdlineArgs, # give the JS harness 30 seconds to deal with # its own timeouts env=browserEnv, timeout=options.timeout + 30.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) mozleak.process_leak_log(self.leakLogFile, leak_thresholds=options.leakThresholds, log=log) log.info("\nREFTEST INFO | runreftest.py | Running tests: end.") finally: self.cleanup(profileDir) return status
def runSerialTests(self, manifests, options, cmdlineArgs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None try: if cmdlineArgs is None: cmdlineArgs = [] profile = self.createReftestProfile(options, manifests) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) status = self.runApp(profile, binary=options.app, cmdargs=cmdlineArgs, # give the JS harness 30 seconds to deal with # its own timeouts env=browserEnv, timeout=options.timeout + 30.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) mozleak.process_leak_log(self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath), ) finally: self.cleanup(profileDir) return status
def process_leaks(self): self.logger.info("PROCESS LEAKS %s" % self.leak_report_file) if self.lsan_handler: self.lsan_handler.process() if self.leak_report_file is not None: mozleak.process_leak_log( self.leak_report_file, leak_thresholds=self.mozleak_thresholds, ignore_missing_leaks=["gmplugin"], log=self.logger, stack_fixer=self.stack_fixer, scope=self.group_metadata.get("scope"), allowed=self.mozleak_allowed )
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 process_leaks(self): self.logger.info("PROCESS LEAKS %s" % self.leak_report_file) if self.lsan_handler: self.lsan_handler.process() if self.leak_report_file is not None: # We have to ignore missing leaks in the tab because it can happen that the # content process crashed and in that case we don't want the test to fail. # Ideally we would record which content process crashed and just skip those. mozleak.process_leak_log(self.leak_report_file, leak_thresholds=self.mozleak_thresholds, ignore_missing_leaks=["tab", "gmplugin"], log=self.logger, stack_fixer=self.stack_fixer, scope=self.group_metadata.get("scope"), allowed=self.mozleak_allowed)
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 runSerialTests(self, manifests, options, cmdargs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info( options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None try: if cmdargs is None: cmdargs = [] if self.use_marionette: cmdargs.append('-marionette') profile = self.createReftestProfile(options, manifests) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) self.log.info("Running with e10s: {}".format(options.e10s)) status = self.runApp( profile, binary=options.app, cmdargs=cmdargs, # give the JS harness 30 seconds to deal with # its own timeouts env=browserEnv, timeout=options.timeout + 30.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) self.log.info("Process mode: {}".format( 'e10s' if options.e10s else 'non-e10s')) mozleak.process_leak_log( self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath), ) finally: self.cleanup(profileDir) return status
def after_stop(self, clean_shutdown=True): self.logger.info("PROCESS LEAKS %s" % self.instance.leak_report_file) if self.lsan_handler: self.lsan_handler.process() if self.instance.leak_report_file is not None: if not clean_shutdown: # If we didn't get a clean shutdown there probably isn't a leak report file self.logger.warning("Firefox didn't exit cleanly, not processing leak logs") else: # We have to ignore missing leaks in the tab because it can happen that the # content process crashed and in that case we don't want the test to fail. # Ideally we would record which content process crashed and just skip those. mozleak.process_leak_log( self.instance.leak_report_file, leak_thresholds=self.mozleak_thresholds, ignore_missing_leaks=["tab", "gmplugin"], log=self.logger, stack_fixer=self.stack_fixer, scope=self.group_metadata.get("scope"), allowed=self.mozleak_allowed)
def runSerialTests(self, manifests, options, cmdlineArgs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info( options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None try: if cmdlineArgs == None: cmdlineArgs = [] profile = self.createReftestProfile(options, manifests) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) log.info("REFTEST INFO | runreftest.py | Running tests: start.\n") status = self.runApp( profile, binary=options.app, cmdargs=cmdlineArgs, # give the JS harness 30 seconds to deal with # its own timeouts env=browserEnv, timeout=options.timeout + 30.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) mozleak.process_leak_log( self.leakLogFile, leak_thresholds=options.leakThresholds, log=log, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath), ) log.info("\nREFTEST INFO | runreftest.py | Running tests: end.") finally: self.cleanup(profileDir) return status
def run_tests(self, options): """ Prepare, configure, run tests and cleanup """ self.setTestRoot(options) manifest = self.build_profile(options) self.logPreamble(self.getActiveTests(options)) # configuring the message logger's buffering self.message_logger.buffering = options.quiet if options.debugger or not options.autorun: timeout = None else: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 timeout = options.timeout + 30.0 self.log.info("runtestsb2g.py | Running tests: start.") status = 0 try: def on_output(line): messages = self.message_logger.write(line) for message in messages: if message['action'] == 'test_start': self.runner.last_test = message['test'] # The logging will be handled by on_output, so we set the stream to # None process_args = {'processOutputLine': on_output, 'stream': None} self.marionette_args['process_args'] = process_args self.marionette_args['profile'] = self.profile self.marionette = Marionette(**self.marionette_args) self.runner = self.marionette.runner self.app_ctx = self.runner.app_ctx self.remote_log = posixpath.join(self.app_ctx.remote_test_root, 'log', 'mochitest.log') if not self.app_ctx.dm.dirExists(posixpath.dirname( self.remote_log)): self.app_ctx.dm.mkDirs(self.remote_log) if options.chrome: # Update chrome manifest file in profile with correct path. self.writeChromeManifest(options) self.leak_report_file = posixpath.join( self.app_ctx.remote_test_root, 'log', 'runtests_leaks.log') # We don't want to copy the host env onto the device, so pass in an # empty env. self.browserEnv = self.buildBrowserEnv(options, env={}) # B2G emulator debug tests still make external connections, so don't # pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug # 1039019). if mozinfo.info[ 'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv: del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] self.runner.env.update(self.browserEnv) # Despite our efforts to clean up servers started by this script, in practice # we still see infrequent cases where a process is orphaned and interferes # with future tests, typically because the old server is keeping the port in use. # Try to avoid those failures by checking for and killing orphan servers before # trying to start new ones. self.killNamedOrphans('ssltunnel') self.killNamedOrphans('xpcshell') self.startServers(options, None) # In desktop mochitests buildTestPath is called before buildURLOptions. This # means options.manifestFile has already been converted to the proper json # style manifest. Not so with B2G, that conversion along with updating the URL # option will happen later. So backup and restore options.manifestFile to # prevent us from trying to pass in an instance of TestManifest via url param. manifestFile = options.manifestFile options.manifestFile = None self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'}) options.manifestFile = manifestFile self.test_script_args.append(not options.emulator) self.test_script_args.append(options.wifi) self.test_script_args.append(options.chrome) self.runner.start(outputTimeout=timeout) self.marionette.wait_for_port() self.marionette.start_session() self.marionette.set_context(self.marionette.CONTEXT_CHROME) # Disable offline status management (bug 777145), otherwise the network # will be 'offline' when the mochitests start. Presumably, the network # won't be offline on a real device, so we only do this for # emulators. self.marionette.execute_script(""" Components.utils.import("resource://gre/modules/Services.jsm"); Services.io.manageOfflineStatus = false; Services.io.offline = false; """) self.marionette.execute_script(""" let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer"; Services.prefs.setBoolPref(SECURITY_PREF, true); if (!testUtils.hasOwnProperty("specialPowersObserver")) { let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); testUtils.specialPowersObserver._loadFrameScript(); } """) if options.chrome: self.app_ctx.dm.removeDir(self.remote_chrome_test_dir) self.app_ctx.dm.mkDir(self.remote_chrome_test_dir) local = super(B2GMochitest, self).getChromeTestDir(options) local = os.path.join(local, "chrome") remote = self.remote_chrome_test_dir self.log.info("pushing %s to %s on device..." % (local, remote)) self.app_ctx.dm.pushDir(local, remote) if os.path.isfile(self.test_script): with open(self.test_script, 'r') as script: self.marionette.execute_script( script.read(), script_args=self.test_script_args) else: self.marionette.execute_script( self.test_script, script_args=self.test_script_args) status = self.runner.wait() if status is None: # the runner has timed out status = 124 local_leak_file = tempfile.NamedTemporaryFile() self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name) self.app_ctx.dm.removeFile(self.leak_report_file) mozleak.process_leak_log( local_leak_file.name, leak_thresholds=options.leakThresholds, ignore_missing_leaks=options.ignoreMissingLeaks, log=self.log, ) except KeyboardInterrupt: self.log.info("runtests.py | Received keyboard interrupt.\n") status = -1 except: traceback.print_exc() self.log.error( "Automation Error: Received unexpected exception while running application\n" ) if hasattr(self, 'runner'): self.runner.check_for_crashes() status = 1 self.stopServers() self.log.info("runtestsb2g.py | Running tests: end.") if manifest is not None: self.cleanup(manifest, options) return status
def runSerialTests(self, manifests, options, cmdargs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info( options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None startAfter = None # When the previous run crashed, we skip the tests we ran before prevStartAfter = None for i in itertools.count(): try: if cmdargs is None: cmdargs = [] if self.use_marionette: cmdargs.append('-marionette') profile = self.createReftestProfile(options, manifests, startAfter=startAfter) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) self.log.info("Running with e10s: {}".format(options.e10s)) status, startAfter = self.runApp( profile, binary=options.app, cmdargs=cmdargs, # give the JS harness 30 seconds to deal with # its own timeouts env=browserEnv, timeout=options.timeout + 30.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) self.log.info("Process mode: {}".format( 'e10s' if options.e10s else 'non-e10s')) mozleak.process_leak_log( self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function( options.utilityPath, options.symbolsPath)) if status == 0: break if startAfter == self.TEST_SEEN_FINAL: self.log.info( "Finished running all tests, skipping resume " "despite non-zero status code: %s" % status) break if startAfter is not None and options.shuffle: self.log.error( "Can not resume from a crash with --shuffle " "enabled. Please consider disabling --shuffle") break if startAfter is not None and options.maxRetries <= i: self.log.error( "Hit maximum number of allowed retries ({}) " "in the test run".format(options.maxRetries)) break if startAfter == prevStartAfter: # If the test stuck on the same test, or there the crashed # test appeared more then once, stop self.log.error("Force stop because we keep running into " "test \"{}\"".format(startAfter)) break prevStartAfter = startAfter # TODO: we need to emit an SUITE-END log if it crashed finally: self.cleanup(profileDir) return status
def run_tests(self, options): """ Prepare, configure, run tests and cleanup """ self.setTestRoot(options) manifest = self.build_profile(options) self.logPreamble(self.getActiveTests(options)) # configuring the message logger's buffering self.message_logger.buffering = options.quiet if options.debugger or not options.autorun: timeout = None else: if not options.timeout: if mozinfo.info['debug']: options.timeout = 420 else: options.timeout = 300 timeout = options.timeout + 30.0 self.log.info("runtestsb2g.py | Running tests: start.") status = 0 try: def on_output(line): messages = self.message_logger.write(line) for message in messages: if message['action'] == 'test_start': self.runner.last_test = message['test'] # The logging will be handled by on_output, so we set the stream to # None process_args = {'processOutputLine': on_output, 'stream': None} self.marionette_args['process_args'] = process_args self.marionette_args['profile'] = self.profile self.marionette = Marionette(**self.marionette_args) self.runner = self.marionette.runner self.app_ctx = self.runner.app_ctx self.remote_log = posixpath.join(self.app_ctx.remote_test_root, 'log', 'mochitest.log') if not self.app_ctx.dm.dirExists( posixpath.dirname( self.remote_log)): self.app_ctx.dm.mkDirs(self.remote_log) if options.chrome: # Update chrome manifest file in profile with correct path. self.writeChromeManifest(options) self.leak_report_file = posixpath.join( self.app_ctx.remote_test_root, 'log', 'runtests_leaks.log') # We don't want to copy the host env onto the device, so pass in an # empty env. self.browserEnv = self.buildBrowserEnv(options, env={}) # B2G emulator debug tests still make external connections, so don't # pass MOZ_DISABLE_NONLOCAL_CONNECTIONS to them for now (bug # 1039019). if mozinfo.info[ 'debug'] and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv: del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS'] self.runner.env.update(self.browserEnv) # Despite our efforts to clean up servers started by this script, in practice # we still see infrequent cases where a process is orphaned and interferes # with future tests, typically because the old server is keeping the port in use. # Try to avoid those failures by checking for and killing orphan servers before # trying to start new ones. self.killNamedOrphans('ssltunnel') self.killNamedOrphans('xpcshell') self.startServers(options, None) # In desktop mochitests buildTestPath is called before buildURLOptions. This # means options.manifestFile has already been converted to the proper json # style manifest. Not so with B2G, that conversion along with updating the URL # option will happen later. So backup and restore options.manifestFile to # prevent us from trying to pass in an instance of TestManifest via url param. manifestFile = options.manifestFile options.manifestFile = None self.buildURLOptions(options, {'MOZ_HIDE_RESULTS_TABLE': '1'}) options.manifestFile = manifestFile self.test_script_args.append(not options.emulator) self.test_script_args.append(options.wifi) self.test_script_args.append(options.chrome) self.runner.start(outputTimeout=timeout) self.marionette.wait_for_port() self.marionette.start_session() self.marionette.set_context(self.marionette.CONTEXT_CHROME) # Disable offline status management (bug 777145), otherwise the network # will be 'offline' when the mochitests start. Presumably, the network # won't be offline on a real device, so we only do this for # emulators. self.marionette.execute_script(""" Components.utils.import("resource://gre/modules/Services.jsm"); Services.io.manageOfflineStatus = false; Services.io.offline = false; """) self.marionette.execute_script(""" let SECURITY_PREF = "security.turn_off_all_security_so_that_viruses_can_take_over_this_computer"; Services.prefs.setBoolPref(SECURITY_PREF, true); if (!testUtils.hasOwnProperty("specialPowersObserver")) { let loader = Components.classes["@mozilla.org/moz/jssubscript-loader;1"] .getService(Components.interfaces.mozIJSSubScriptLoader); loader.loadSubScript("chrome://specialpowers/content/SpecialPowersObserver.js", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); testUtils.specialPowersObserver._loadFrameScript(); } """) if options.chrome: self.app_ctx.dm.removeDir(self.remote_chrome_test_dir) self.app_ctx.dm.mkDir(self.remote_chrome_test_dir) local = super(B2GMochitest, self).getChromeTestDir(options) local = os.path.join(local, "chrome") remote = self.remote_chrome_test_dir self.log.info( "pushing %s to %s on device..." % (local, remote)) self.app_ctx.dm.pushDir(local, remote) if os.path.isfile(self.test_script): with open(self.test_script, 'r') as script: self.marionette.execute_script( script.read(), script_args=self.test_script_args) else: self.marionette.execute_script( self.test_script, script_args=self.test_script_args) status = self.runner.wait() if status is None: # the runner has timed out status = 124 local_leak_file = tempfile.NamedTemporaryFile() self.app_ctx.dm.getFile( self.leak_report_file, local_leak_file.name) self.app_ctx.dm.removeFile(self.leak_report_file) mozleak.process_leak_log( local_leak_file.name, leak_thresholds=options.leakThresholds, ignore_missing_leaks=options.ignoreMissingLeaks, log=self.log, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath), ) except KeyboardInterrupt: self.log.info("runtests.py | Received keyboard interrupt.\n") status = -1 except: traceback.print_exc() self.log.error( "Automation Error: Received unexpected exception while running application\n") if hasattr(self, 'runner'): self.runner.check_for_crashes() status = 1 self.stopServers() self.log.info("runtestsb2g.py | Running tests: end.") if manifest is not None: self.cleanup(manifest, options) return status
def runSerialTests(self, manifests, options, cmdargs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs, options.debuggerInteractive) profileDir = None startAfter = None # When the previous run crashed, we skip the tests we ran before prevStartAfter = None for i in itertools.count(): try: if cmdargs is None: cmdargs = [] if self.use_marionette: cmdargs.append('-marionette') profile = self.createReftestProfile(options, manifests, startAfter=startAfter) profileDir = profile.profile # name makes more sense # browser environment browserEnv = self.buildBrowserEnv(options, profileDir) self.log.info("Running with e10s: {}".format(options.e10s)) status, startAfter = self.runApp(profile, binary=options.app, cmdargs=cmdargs, env=browserEnv, # We generally want the JS harness or marionette # to handle timeouts if they can. # The default JS harness timeout is currently # 300 seconds (default options.timeout). # The default Marionette socket timeout is # currently 360 seconds. # Give the JS harness extra time to deal with # its own timeouts and try to usually exceed # the 360 second marionette socket timeout. # See bug 479518 and bug 1414063. timeout=options.timeout + 70.0, symbolsPath=options.symbolsPath, options=options, debuggerInfo=debuggerInfo) self.log.info("Process mode: {}".format('e10s' if options.e10s else 'non-e10s')) mozleak.process_leak_log(self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath)) if status == 0: break if startAfter == self.TEST_SEEN_FINAL: self.log.info("Finished running all tests, skipping resume " "despite non-zero status code: %s" % status) break if startAfter is not None and options.shuffle: self.log.error("Can not resume from a crash with --shuffle " "enabled. Please consider disabling --shuffle") break if startAfter is not None and options.maxRetries <= i: self.log.error("Hit maximum number of allowed retries ({}) " "in the test run".format(options.maxRetries)) break if startAfter == prevStartAfter: # If the test stuck on the same test, or there the crashed # test appeared more then once, stop self.log.error("Force stop because we keep running into " "test \"{}\"".format(startAfter)) break prevStartAfter = startAfter # TODO: we need to emit an SUITE-END log if it crashed finally: self.cleanup(profileDir) return status
def runSerialTests(self, manifests, options, cmdargs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs, options.debuggerInteractive) tests = None if self.parse_manifest: tests = self.getActiveTests(manifests, options) ids = [t['identifier'] for t in tests] self.log.suite_start(ids, name=options.suite) startAfter = None # When the previous run crashed, we skip the tests we ran before prevStartAfter = None for i in itertools.count(): status, startAfter, results = self.runApp( options, tests=tests, manifests=manifests, cmdargs=cmdargs, # We generally want the JS harness or marionette # to handle timeouts if they can. # The default JS harness timeout is currently # 300 seconds (default options.timeout). # The default Marionette socket timeout is # currently 360 seconds. # Give the JS harness extra time to deal with # its own timeouts and try to usually exceed # the 360 second marionette socket timeout. # See bug 479518 and bug 1414063. timeout=options.timeout + 70.0, symbolsPath=options.symbolsPath, debuggerInfo=debuggerInfo ) mozleak.process_leak_log(self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function(options.utilityPath, options.symbolsPath)) if status == 0: break if startAfter == self.TEST_SEEN_FINAL: self.log.info("Finished running all tests, skipping resume " "despite non-zero status code: %s" % status) break if startAfter is not None and options.shuffle: self.log.error("Can not resume from a crash with --shuffle " "enabled. Please consider disabling --shuffle") break if startAfter is not None and options.maxRetries <= i: self.log.error("Hit maximum number of allowed retries ({}) " "in the test run".format(options.maxRetries)) break if startAfter == prevStartAfter: # If the test stuck on the same test, or there the crashed # test appeared more then once, stop self.log.error("Force stop because we keep running into " "test \"{}\"".format(startAfter)) break prevStartAfter = startAfter # TODO: we need to emit an SUITE-END log if it crashed if self.parse_manifest: self.log.suite_end(extra={'results': results}) return status