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 run(**kwargs): if kwargs.get('tests'): self.lastTest = kwargs['tests'][-1]['identifier'] if not isinstance(self.lastTest, basestring): self.lastTest = ' '.join(self.lastTest) status = self.runApp( options, 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, debuggerInfo=debuggerInfo, symbolsPath=options.symbolsPath, **kwargs) mozleak.process_leak_log(self.leakLogFile, leak_thresholds=options.leakThresholds, stack_fixer=get_stack_fixer_function( options.utilityPath, options.symbolsPath)) return status
def __init__(self, logger, stackfix_dir, symbols_path, asan): """Filter for handling Firefox process output. This receives Firefox process output in the __call__ function, does any additional processing that's required, and decides whether to log the output. Because the Firefox process can be started before we know which filters are going to be required, we buffer all output until setup() is called. This is responsible for doing the final configuration of the output handlers. """ self.logger = logger # These are filled in after setup() is called self.instance = None self.symbols_path = symbols_path if stackfix_dir: self.stack_fixer = get_stack_fixer_function( stackfix_dir, self.symbols_path) else: self.stack_fixer = None self.asan = asan self.lsan_handler = None self.mozleak_allowed = None self.mozleak_thresholds = None self.group_metadata = {} self.line_buffer = [] self.setup_ran = False
def __init__(self, logger, command, symbols_path=None, stackfix_dir=None, asan=False, leak_report_file=None): """Filter for handling Firefox process output. This receives Firefox process output in the __call__ function, does any additional processing that's required, and decides whether to log the output. Because the Firefox process can be started before we know which filters are going to be required, we buffer all output until setup() is called. This is responsible for doing the final configuration of the output handlers. """ super().__init__(logger, command) self.symbols_path = symbols_path if stackfix_dir: # We hide errors because they cause disconcerting `CRITICAL` # warnings in web platform test output. self.stack_fixer = get_stack_fixer_function(stackfix_dir, self.symbols_path, hideErrors=True) else: self.stack_fixer = None self.asan = asan self.leak_report_file = leak_report_file # These are filled in after configure_handlers() is called self.lsan_handler = None self.mozleak_allowed = None self.mozleak_thresholds = None self.group_metadata = {}
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 __init__(self, logger, binary, prefs_root, debug_info=None, symbols_path=None, stackwalk_binary=None, certutil_binary=None, ca_certificate_path=None, e10s=False, stackfix_dir=None): 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 if self.symbols_path and stackfix_dir: self.stack_fixer = get_stack_fixer_function( stackfix_dir, self.symbols_path) else: self.stack_fixer = None
def run_gtest(self, prog, xre_path, cwd, symbols_path=None, utility_path=None, enable_webrender=False): """ Run a single C++ unit test program. Arguments: * prog: The path to the test program to run. * env: The environment to use for running the program. * cwd: The directory to run tests from (support files will be found in this direcotry). * symbols_path: A path to a directory containing Breakpad-formatted symbol files for producing stack traces on crash. * utility_path: A path to a directory containing utility programs. currently used to locate a stack fixer to provide symbols symbols for assertion stacks. Return True if the program exits with a zero status, False otherwise. """ self.xre_path = xre_path env = self.build_environment(enable_webrender) log.info("Running gtest") if cwd and not os.path.isdir(cwd): os.makedirs(cwd) stream_output = mozprocess.StreamOutput(sys.stdout) process_output = stream_output if utility_path: stack_fixer = get_stack_fixer_function(utility_path, symbols_path) if stack_fixer: def f(line): return stream_output(stack_fixer(line)) process_output = f proc = mozprocess.ProcessHandler([prog, "-unittest", "--gtest_death_test_style=threadsafe"], cwd=cwd, env=env, processOutputLine=process_output) # TODO: After bug 811320 is fixed, don't let .run() kill the process, # instead use a timeout in .wait() and then kill to get a stack. proc.run(timeout=GTests.TEST_PROC_TIMEOUT, outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) proc.wait() log.info("gtest | process wait complete, returncode=%s" % proc.proc.returncode) if proc.timedOut: if proc.outputTimedOut: log.testFail("gtest | timed out after %d seconds without output", GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) else: log.testFail("gtest | timed out after %d seconds", GTests.TEST_PROC_TIMEOUT) return False if mozcrash.check_for_crashes(cwd, symbols_path, test_name="gtest"): # mozcrash will output the log failure line for us. return False result = proc.proc.returncode == 0 if not result: log.testFail("gtest | test failed with return code %d", proc.proc.returncode) return result
def run_gtest(self, prog, xre_path, cwd, symbols_path=None, utility_path=None): """ Run a single C++ unit test program. Arguments: * prog: The path to the test program to run. * env: The environment to use for running the program. * cwd: The directory to run tests from (support files will be found in this direcotry). * symbols_path: A path to a directory containing Breakpad-formatted symbol files for producing stack traces on crash. * utility_path: A path to a directory containing utility programs. currently used to locate a stack fixer to provide symbols symbols for assertion stacks. Return True if the program exits with a zero status, False otherwise. """ self.xre_path = xre_path env = self.build_environment() log.info("Running gtest") if cwd and not os.path.isdir(cwd): os.makedirs(cwd) stream_output = mozprocess.StreamOutput(sys.stdout) process_output = stream_output if utility_path: stack_fixer = get_stack_fixer_function(utility_path, symbols_path) if stack_fixer: process_output = lambda line: stream_output(stack_fixer(line)) proc = mozprocess.ProcessHandler([prog, "-unittest", "--gtest_death_test_style=threadsafe"], cwd=cwd, env=env, processOutputLine=process_output) #TODO: After bug 811320 is fixed, don't let .run() kill the process, # instead use a timeout in .wait() and then kill to get a stack. proc.run(timeout=GTests.TEST_PROC_TIMEOUT, outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) proc.wait() if proc.timedOut: if proc.outputTimedOut: log.testFail("gtest | timed out after %d seconds without output", GTests.TEST_PROC_NO_OUTPUT_TIMEOUT) else: log.testFail("gtest | timed out after %d seconds", GTests.TEST_PROC_TIMEOUT) return False if mozcrash.check_for_crashes(cwd, symbols_path, test_name="gtest"): # mozcrash will output the log failure line for us. return False result = proc.proc.returncode == 0 if not result: log.testFail("gtest | test failed with return code %d", proc.proc.returncode) return result
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 status = 1 # Just to start the loop while status != 0: 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)) self.cleanup(profileDir) 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 == 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) 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 __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, enable_webrender=False, lsan_dir=None, stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False, asan=False, stylo_threads=1, chaos_mode_flags=None, config=None, browser_channel="nightly", headless=None, **kwargs): 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.enable_webrender = enable_webrender 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.asan = asan self.lsan_dir = lsan_dir self.lsan_allowed = None self.lsan_max_stack_depth = None self.mozleak_allowed = None self.mozleak_thresholds = None self.leak_check = leak_check self.leak_report_file = None self.lsan_handler = None self.stylo_threads = stylo_threads self.chaos_mode_flags = chaos_mode_flags self.browser_channel = browser_channel self.headless = headless
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, stackfix_dir=None): 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 if self.symbols_path and stackfix_dir: self.stack_fixer = get_stack_fixer_function(stackfix_dir, self.symbols_path) else: self.stack_fixer = None
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 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, 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 stack_fixer(self): """ return get_stack_fixer_function, if any, to use on the output lines """ return get_stack_fixer_function(self.utilityPath, self.symbolsPath)
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
def __init__(self, log, utilityPath, symbolsPath=None): self.stack_fixer_function = get_stack_fixer_function( utilityPath, symbolsPath) self.log = log
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 __init__(self, log, utilityPath, symbolsPath=None): self.stack_fixer_function = get_stack_fixer_function(utilityPath, symbolsPath) self.log = log
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 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 # Increase the timeout to fix bug 1208725 self.marionette_args['socket_timeout'] = 720 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.start_script_args.append(not options.emulator) self.start_script_args.append(options.wifi) self.start_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.jsm", testUtils); testUtils.specialPowersObserver = new testUtils.SpecialPowersObserver(); testUtils.specialPowersObserver.init(); } """) if options.chrome: self.app_ctx.dm.removeDir(self.remote_chrome_test_dir) self.app_ctx.dm.mkDir(self.remote_chrome_test_dir) local = MochitestBase.getChromeTestDir(self, 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) self.execute_start_script() 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 __init__(self, log, utilityPath, symbolsPath=None): self.stack_fixer_function = get_stack_fixer_function( utilityPath, symbolsPath) self.log = log # needed for b2gautomation.py self.suite_finished = False
def __init__(self, log, utilityPath, symbolsPath=None): self.stack_fixer_function = get_stack_fixer_function(utilityPath, symbolsPath) self.log = log # needed for b2gautomation.py self.suite_finished = False
def __init__(self, log, utilityPath, symbolsPath=None): self.stack_fixer_function = get_stack_fixer_function( utilityPath, symbolsPath) self.log = log self.proc_name = None self.results = defaultdict(int)
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