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) processLeakLog(self.leakLogFile, options) log.info("\nREFTEST INFO | runreftest.py | Running tests: end.") finally: self.cleanup(profileDir) return status
def run(self, params, debug=False, debugger=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" args = [path.join("target", "servo")] # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Prepend the debugger args. args = ([self.debuggerInfo.path] + self.debuggerInfo.args + args + params) else: args = args + params subprocess.check_call(args, env=env)
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 run(self, params, release=False, dev=False, debug=False, debugger=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" args = [self.get_binary_path(release, dev)] # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Prepend the debugger args. args = [self.debuggerInfo.path] + self.debuggerInfo.args + args + params else: args = args + params try: subprocess.check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def run(self, params, release=False, dev=False, android=False, debug=False, debugger=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop com.mozilla.servo", "echo servo >/sdcard/servo/android_params" ] for param in params: script += [ "echo '%s' >>/sdcard/servo/android_params" % param.replace("'", "\\'") ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", "exit" ] shell = subprocess.Popen(["adb", "shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [self.get_binary_path(release, dev)] # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Prepend the debugger args. args = ([self.debuggerInfo.path] + self.debuggerInfo.args + args + params) else: args = args + params try: subprocess.check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def debug(self, params, remote, background, debugger, debugparams, slowscript): # Parameters come from the CLI. We need to convert them before their use. if debugparams: import pymake.process argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd()) if badchar: print("The +debugparams you passed require a real shell to parse them.") print("(We can't handle the %r character.)" % (badchar,)) return 1 debugparams = argv; import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugparams) # We could not find the information about the desired debugger. if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 extra_env = { 'MOZ_CRASHREPORTER_DISABLE' : '1' } binpath = None try: binpath = self.get_binary_path('app') except Exception as e: print("It looks like your program isn't built.", "You can run |mach build| to build it.") print(e) return 1 # Build the list of arguments to pass to run_process args = [self.debuggerInfo.path] + self.debuggerInfo.args args.append(binpath) if not remote: args.append('-no-remote') if not background and sys.platform == 'darwin': args.append('-foreground') if params: args.extend(params) if '-profile' not in params and '-P' not in params: path = os.path.join(self.topobjdir, 'tmp', 'scratch_user') if not os.path.isdir(path): os.makedirs(path) args.append('-profile') args.append(path) if not slowscript: extra_env['JS_DISABLE_SLOW_SCRIPT_SIGNALS'] = '1' return self.run_process(args=args, append_env=extra_env, ensure_exit_code=False, pass_thru=True)
def run(self, binary, params, debug, debugger, debugger_args): try: binpath = self.get_binary_path("geckodriver") except Exception as e: print("It looks like geckodriver isn't built. " "Add ac_add_options --enable-geckodrver to your mozconfig ", "and run |mach build| to build it.") print(e) return 1 args = [binpath] if params: args.extend(params) if binary is None: binary = self.get_binary_path("app") args.extend(["--binary", binary]) if debug or debugger or debugger_args: if "INSIDE_EMACS" in os.environ: self.log_manager.terminal_handler.setLevel(logging.WARNING) import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) if debugger: self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugger_args) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Parameters come from the CLI. We need to convert them before # their use. if debugger_args: from mozbuild import shellutil try: debugger_args = shellutil.split(debugger_args) except shellutil.MetaCharacterException as e: print("The --debugger-args you passed require a real shell to parse them.") print("(We can't handle the %r character.)" % e.char) return 1 # Prepend the debugger args. args = [self.debuggerInfo.path] + self.debuggerInfo.args + args return self.run_process(args=args, ensure_exit_code=False, pass_thru=True)
def find_debugger_info(debug, debugger, debugger_args): debuggerInfo = None if debug or debugger or debugger_args: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) debuggerInfo = None if debugger: debuggerInfo = mozdebug.get_debugger_info(debugger, debugger_args) if debuggerInfo is None: raise TalosError('Could not find a suitable debugger in your PATH.') return debuggerInfo
def prepend_debugger_args(self, args, debugger, debugger_args): """ Given an array with program arguments, prepend arguments to run it under a debugger. :param args: The executable and arguments used to run the process normally. :param debugger: The debugger to use, or empty to use the default debugger. :param debugger_args: Any additional parameters to pass to the debugger. """ import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) if debugger: debuggerInfo = mozdebug.get_debugger_info(debugger, debugger_args) if not debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Parameters come from the CLI. We need to convert them before # their use. if debugger_args: import pymake.process argv, badchar = pymake.process.clinetoargv(debugger_args, os.getcwd()) if badchar: print("The --debugger_args you passed require a real shell to parse them.") print("(We can't handle the %r character.)" % (badchar,)) return 1 debugger_args = argv # Prepend the debugger args. args = [debuggerInfo.path] + debuggerInfo.args + args return args
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, headless=False, software=False, bin=None, emulator=False, usb=False, nightly=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" # Make --debugger imply --debug if debugger: debug = True if android is None: android = self.config["build"]["android"] if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop org.mozilla.servo", ] json_params = shell_quote(json.dumps(params)) extra = "-e servoargs " + json_params rust_log = env.get("RUST_LOG", None) if rust_log: extra += " -e servolog " + rust_log script += [ "am start " + extra + " org.mozilla.servo/org.mozilla.servo.MainActivity", "sleep 0.5", "echo Servo PID: $(pidof org.mozilla.servo)", "exit" ] args = [self.android_adb_path(env)] if emulator and usb: print("Cannot run in both emulator and USB at the same time.") return 1 if emulator: args += ["-e"] if usb: args += ["-d"] shell = subprocess.Popen(args + ["shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(release, dev)] if headless: set_osmesa_env(args[0], env) args.append('-z') if software: if not is_linux(): print("Software rendering is only supported on Linux at the moment.") return env['LIBGL_ALWAYS_SOFTWARE'] = "1" # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) except (OSError, subprocess.CalledProcessError): pass else: command = rustCommand # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, browserhtml=False, headless=False, software=False): env = self.build_env() env["RUST_BACKTRACE"] = "1" # Make --debugger imply --debug if debugger: debug = True if android is None: android = self.config["build"]["android"] if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop com.mozilla.servo", "echo servo >/sdcard/servo/android_params" ] for param in params: script += [ "echo '%s' >>/sdcard/servo/android_params" % param.replace("'", "\\'") ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", "exit" ] shell = subprocess.Popen(["adb", "shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [self.get_binary_path(release, dev)] if browserhtml: browserhtml_path = get_browserhtml_path(args[0]) if is_macosx(): # Enable borderless on OSX args = args + ['-b'] elif is_windows(): # Convert to a relative path to avoid mingw -> Windows path conversions browserhtml_path = path.relpath(browserhtml_path, os.getcwd()) args = args + ['--pref', 'dom.mozbrowser.enabled', '--pref', 'dom.forcetouch.enabled', '--pref', 'shell.builtin-key-shortcuts.enabled=false', path.join(browserhtml_path, 'index.html')] if headless: set_osmesa_env(args[0], env) args.append('-z') if software: if not is_linux(): print("Software rendering is only supported on Linux at the moment.") return env['LIBGL_ALWAYS_SOFTWARE'] = "1" # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) except (OSError, subprocess.CalledProcessError): pass else: command = rustCommand # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def check_args(kwargs): set_from_config(kwargs) if kwargs["product"] is None: kwargs["product"] = "firefox" if kwargs["manifest_update"] is None: kwargs["manifest_update"] = True if "sauce" in kwargs["product"]: kwargs["pause_after_test"] = False if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print >> sys.stderr, "Binary path %s does not exist" % kwargs[ "binary"] sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x: os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print >> sys.stderr, "openssl-binary argument missing or not a valid executable" sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs[ "product"] == "firefox" and kwargs["certutil_binary"]: path = exe_path(kwargs["certutil_binary"]) if path is None: print >> sys.stderr, "certutil-binary argument missing or not a valid executable" sys.exit(1) kwargs["certutil_binary"] = path if kwargs['extra_prefs']: # If a single pref is passed in as a string, make it a list if type(kwargs['extra_prefs']) in (str, unicode): kwargs['extra_prefs'] = [kwargs['extra_prefs']] missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) if missing: print >> sys.stderr, "Preferences via --setpref must be in key=value format" sys.exit(1) kwargs['extra_prefs'] = [ tuple(prefarg.split('=', 1)) for prefarg in kwargs['extra_prefs'] ] if kwargs["reftest_internal"] is None: kwargs["reftest_internal"] = True return kwargs
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, headless=False, software=False, bin=None, emulator=False, usb=False, nightly=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" # Make --debugger imply --debug if debugger: debug = True if android is None: android = self.config["build"]["android"] if android: if debug: print( "Android on-device debugging is not supported by mach yet. See" ) print( "https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device" ) return script = [ "am force-stop org.mozilla.servo", ] json_params = shell_quote(json.dumps(params)) extra = "-e servoargs " + json_params rust_log = env.get("RUST_LOG", None) if rust_log: extra += " -e servolog " + rust_log script += [ "am start " + extra + " org.mozilla.servo/org.mozilla.servo.MainActivity", "sleep 0.5", "echo Servo PID: $(pidof org.mozilla.servo)", "exit" ] args = [self.android_adb_path(env)] if emulator and usb: print("Cannot run in both emulator and USB at the same time.") return 1 if emulator: args += ["-e"] if usb: args += ["-d"] shell = subprocess.Popen(args + ["shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [ bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(release, dev) ] if headless: set_osmesa_env(args[0], env) args.append('-z') if software: if not is_linux(): print( "Software rendering is only supported on Linux at the moment." ) return env['LIBGL_ALWAYS_SOFTWARE'] = "1" # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) except (OSError, subprocess.CalledProcessError): pass else: command = rustCommand # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
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 check_args(kwargs): set_from_config(kwargs) for test_paths in kwargs["test_paths"].itervalues(): if not ("tests_path" in test_paths and "metadata_path" in test_paths): print "Fatal: must specify both a test path and metadata path" sys.exit(1) for key, path in test_paths.iteritems(): name = key.split("_", 1)[0] if not os.path.exists(path): print "Fatal: %s path %s does not exist" % (name, path) sys.exit(1) if not os.path.isdir(path): print "Fatal: %s path %s is not a directory" % (name, path) sys.exit(1) if kwargs["product"] is None: kwargs["product"] = "firefox" if "sauce" in kwargs["product"]: kwargs["pause_after_test"] = False if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print >> sys.stderr, "Binary path %s does not exist" % kwargs[ "binary"] sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x: os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print >> sys.stderr, "openssl-binary argument missing or not a valid executable" sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs[ "product"] == "firefox" and kwargs["certutil_binary"]: path = exe_path(kwargs["certutil_binary"]) if path is None: print >> sys.stderr, "certutil-binary argument missing or not a valid executable" sys.exit(1) kwargs["certutil_binary"] = path if kwargs['extra_prefs']: missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) if missing: print >> sys.stderr, "Preferences via --setpref must be in key=value format" sys.exit(1) kwargs['extra_prefs'] = [ tuple(prefarg.split('=', 1)) for prefarg in kwargs['extra_prefs'] ] if kwargs["reftest_internal"] is None: # Default to the internal reftest implementation on Linux and OSX kwargs["reftest_internal"] = sys.platform.startswith( "linux") or sys.platform.startswith("darwin") return kwargs
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, browserhtml=False, headless=False, software=False): env = self.build_env() env["RUST_BACKTRACE"] = "1" # Make --debugger imply --debug if debugger: debug = True if android is None: android = self.config["build"]["android"] if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop com.mozilla.servo", "echo servo >/sdcard/Android/data/com.mozilla.servo/files/android_params" ] for param in params: script += [ "echo '%s' >>/sdcard/Android/data/com.mozilla.servo/files/android_params" % param.replace("'", "\\'") ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", "exit" ] shell = subprocess.Popen(["adb", "shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [self.get_binary_path(release, dev)] if browserhtml: browserhtml_path = get_browserhtml_path(args[0]) if is_macosx(): # Enable borderless on OSX args = args + ['-b'] elif is_windows(): # Convert to a relative path to avoid mingw -> Windows path conversions browserhtml_path = path.relpath(browserhtml_path, os.getcwd()) args = args + ['--pref', 'dom.mozbrowser.enabled', '--pref', 'dom.forcetouch.enabled', '--pref', 'shell.builtin-key-shortcuts.enabled=false', path.join(browserhtml_path, 'index.html')] if headless: set_osmesa_env(args[0], env) args.append('-z') if software: if not is_linux(): print("Software rendering is only supported on Linux at the moment.") return env['LIBGL_ALWAYS_SOFTWARE'] = "1" # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) except (OSError, subprocess.CalledProcessError): pass else: command = rustCommand # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def debug(self, params, remote, background, debugger, debugparams, slowscript): # Parameters come from the CLI. We need to convert them before their use. if debugparams: import pymake.process argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd()) if badchar: print( "The +debugparams you passed require a real shell to parse them." ) print("(We can't handle the %r character.)" % (badchar, )) return 1 debugparams = argv import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugparams) # We could not find the information about the desired debugger. if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 extra_env = {'MOZ_CRASHREPORTER_DISABLE': '1'} binpath = None try: binpath = self.get_binary_path('app') except Exception as e: print("It looks like your program isn't built.", "You can run |mach build| to build it.") print(e) return 1 # Build the list of arguments to pass to run_process args = [self.debuggerInfo.path] + self.debuggerInfo.args args.append(binpath) if not remote: args.append('-no-remote') if not background and sys.platform == 'darwin': args.append('-foreground') if params: args.extend(params) if '-profile' not in params and '-P' not in params: path = os.path.join(self.topobjdir, 'tmp', 'scratch_user') if not os.path.isdir(path): os.makedirs(path) args.append('-profile') args.append(path) if not slowscript: extra_env['JS_DISABLE_SLOW_SCRIPT_SIGNALS'] = '1' return self.run_process(args=args, append_env=extra_env, ensure_exit_code=False, pass_thru=True)
def check_args(kwargs): set_from_config(kwargs) if kwargs["product"] is None: kwargs["product"] = "firefox" if kwargs["manifest_update"] is None: kwargs["manifest_update"] = True if "sauce" in kwargs["product"]: kwargs["pause_after_test"] = False if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print("Binary path %s does not exist" % kwargs["binary"], file=sys.stderr) sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x:os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print("openssl-binary argument missing or not a valid executable", file=sys.stderr) sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox" and kwargs["certutil_binary"]: path = exe_path(kwargs["certutil_binary"]) if path is None: print("certutil-binary argument missing or not a valid executable", file=sys.stderr) sys.exit(1) kwargs["certutil_binary"] = path if kwargs['extra_prefs']: # If a single pref is passed in as a string, make it a list if type(kwargs['extra_prefs']) in (str, unicode): kwargs['extra_prefs'] = [kwargs['extra_prefs']] missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) if missing: print("Preferences via --setpref must be in key=value format", file=sys.stderr) sys.exit(1) kwargs['extra_prefs'] = [tuple(prefarg.split('=', 1)) for prefarg in kwargs['extra_prefs']] if kwargs["reftest_internal"] is None: kwargs["reftest_internal"] = True if kwargs["lsan_dir"] is None: kwargs["lsan_dir"] = kwargs["prefs_root"] if kwargs["reftest_screenshot"] is None: kwargs["reftest_screenshot"] = "unexpected" return kwargs
def run(self, params, remote, background, noprofile, debug, debugger, debugparams, slowscript, dmd, mode, sample_below, max_frames, show_dump_stats): try: binpath = self.get_binary_path('app') except Exception as e: print("It looks like your program isn't built.", "You can run |mach build| to build it.") print(e) return 1 args = [binpath] if params: args.extend(params) if not remote: args.append('-no-remote') if not background and sys.platform == 'darwin': args.append('-foreground') no_profile_option_given = \ all(p not in params for p in ['-profile', '--profile', '-P']) if no_profile_option_given and not noprofile: path = os.path.join(self.topobjdir, 'tmp', 'scratch_user') if not os.path.isdir(path): os.makedirs(path) args.append('-profile') args.append(path) extra_env = {} if debug or debugger or debugparams: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking) if debugger: self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugparams) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Parameters come from the CLI. We need to convert them before # their use. if debugparams: import pymake.process argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd()) if badchar: print("The --debugparams you passed require a real shell to parse them.") print("(We can't handle the %r character.)" % (badchar,)) return 1 debugparams = argv; if not slowscript: extra_env['JS_DISABLE_SLOW_SCRIPT_SIGNALS'] = '1' extra_env['MOZ_CRASHREPORTER_DISABLE'] = '1' # Prepend the debugger args. args = [self.debuggerInfo.path] + self.debuggerInfo.args + args if dmd: dmd_params = [] if mode: dmd_params.append('--mode=' + mode) if sample_below: dmd_params.append('--sample-below=' + sample_below) if max_frames: dmd_params.append('--max-frames=' + max_frames) if show_dump_stats: dmd_params.append('--show-dump-stats=yes') bin_dir = os.path.dirname(binpath) lib_name = self.substs['DLL_PREFIX'] + 'dmd' + self.substs['DLL_SUFFIX'] dmd_lib = os.path.join(bin_dir, lib_name) if not os.path.exists(dmd_lib): print("Please build with |--enable-dmd| to use DMD.") return 1 env_vars = { "Darwin": { "DYLD_INSERT_LIBRARIES": dmd_lib, "LD_LIBRARY_PATH": bin_dir, }, "Linux": { "LD_PRELOAD": dmd_lib, "LD_LIBRARY_PATH": bin_dir, }, "WINNT": { "MOZ_REPLACE_MALLOC_LIB": dmd_lib, }, } arch = self.substs['OS_ARCH'] if dmd_params: env_vars[arch]["DMD"] = " ".join(dmd_params) extra_env.update(env_vars.get(arch, {})) return self.run_process(args=args, ensure_exit_code=False, pass_thru=True, append_env=extra_env)
def check_args(kwargs): set_from_config(kwargs) for test_paths in kwargs["test_paths"].itervalues(): if not ("tests_path" in test_paths and "metadata_path" in test_paths): print "Fatal: must specify both a test path and metadata path" sys.exit(1) for key, path in test_paths.iteritems(): name = key.split("_", 1)[0] if not os.path.exists(path): print "Fatal: %s path %s does not exist" % (name, path) sys.exit(1) if not os.path.isdir(path): print "Fatal: %s path %s is not a directory" % (name, path) sys.exit(1) if kwargs["product"] is None: kwargs["product"] = "firefox" if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print >> sys.stderr, "Binary path %s does not exist" % kwargs[ "binary"] sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x: os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print >> sys.stderr, "openssl-binary argument missing or not a valid executable" sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox": path = exe_path(kwargs["certutil_binary"]) if path is None: print >> sys.stderr, "certutil-binary argument missing or not a valid executable" sys.exit(1) kwargs["certutil_binary"] = path return kwargs
def run_mochitest_general(self, flavor=None, test_objects=None, resolve_tests=True, **kwargs): from mochitest_options import ALL_FLAVORS from mozlog.commandline import setup_logging from mozlog.handlers import StreamHandler from moztest.resolve import get_suite_definition # TODO: This is only strictly necessary while mochitest is using Python # 2 and can be removed once the command is migrated to Python 3. self.activate_virtualenv() buildapp = None for app in SUPPORTED_APPS: if conditions.is_buildapp_in(self, apps=[app]): buildapp = app break flavors = None if flavor: for fname, fobj in ALL_FLAVORS.iteritems(): if flavor in fobj['aliases']: if buildapp not in fobj['enabled_apps']: continue flavors = [fname] break else: flavors = [f for f, v in ALL_FLAVORS.iteritems() if buildapp in v['enabled_apps']] from mozbuild.controller.building import BuildDriver self._ensure_state_subdir_exists('.') test_paths = kwargs['test_paths'] kwargs['test_paths'] = [] if kwargs.get('debugger', None): import mozdebug if not mozdebug.get_debugger_info(kwargs.get('debugger')): sys.exit(1) mochitest = self._spawn(MochitestRunner) tests = [] if resolve_tests: tests = mochitest.resolve_tests(test_paths, test_objects, cwd=self._mach_context.cwd) if not kwargs.get('log'): # Create shared logger format_args = {'level': self._mach_context.settings['test']['level']} if len(tests) == 1: format_args['verbose'] = True format_args['compact'] = False default_format = self._mach_context.settings['test']['format'] kwargs['log'] = setup_logging('mach-mochitest', kwargs, {default_format: sys.stdout}, format_args) for handler in kwargs['log'].handlers: if isinstance(handler, StreamHandler): handler.formatter.inner.summary_on_shutdown = True driver = self._spawn(BuildDriver) driver.install_tests() subsuite = kwargs.get('subsuite') if subsuite == 'default': kwargs['subsuite'] = None suites = defaultdict(list) unsupported = set() for test in tests: # Filter out non-mochitests and unsupported flavors. if test['flavor'] not in ALL_FLAVORS: continue key = (test['flavor'], test.get('subsuite', '')) if test['flavor'] not in flavors: unsupported.add(key) continue if subsuite == 'default': # "--subsuite default" means only run tests that don't have a subsuite if test.get('subsuite'): unsupported.add(key) continue elif subsuite and test.get('subsuite', '') != subsuite: unsupported.add(key) continue suites[key].append(test) if ('mochitest', 'media') in suites: req = os.path.join('testing', 'tools', 'websocketprocessbridge', 'websocketprocessbridge_requirements.txt') self.virtualenv_manager.activate() self.virtualenv_manager.install_pip_requirements(req, require_hashes=False) # sys.executable is used to start the websocketprocessbridge, though for some # reason it doesn't get set when calling `activate_this.py` in the virtualenv. sys.executable = self.virtualenv_manager.python_path # This is a hack to introduce an option in mach to not send # filtered tests to the mochitest harness. Mochitest harness will read # the master manifest in that case. if not resolve_tests: for flavor in flavors: key = (flavor, kwargs.get('subsuite')) suites[key] = [] if not suites: # Make it very clear why no tests were found if not unsupported: print(TESTS_NOT_FOUND.format('\n'.join( sorted(list(test_paths or test_objects))))) return 1 msg = [] for f, s in unsupported: fobj = ALL_FLAVORS[f] apps = fobj['enabled_apps'] name = fobj['aliases'][0] if s: name = '{} --subsuite {}'.format(name, s) if buildapp not in apps: reason = 'requires {}'.format(' or '.join(apps)) else: reason = 'excluded by the command line' msg.append(' mochitest -f {} ({})'.format(name, reason)) print(SUPPORTED_TESTS_NOT_FOUND.format( buildapp, '\n'.join(sorted(msg)))) return 1 if buildapp == 'android': from mozrunner.devices.android_device import (verify_android_device, InstallIntent) app = kwargs.get('app') if not app: app = "org.mozilla.geckoview.test" device_serial = kwargs.get('deviceSerial') install = InstallIntent.NO if kwargs.get('no_install') else InstallIntent.YES # verify installation verify_android_device(self, install=install, xre=False, network=True, app=app, device_serial=device_serial) run_mochitest = mochitest.run_android_test else: run_mochitest = mochitest.run_desktop_test overall = None for (flavor, subsuite), tests in sorted(suites.items()): suite_name, suite = get_suite_definition(flavor, subsuite) if 'test_paths' in suite['kwargs']: del suite['kwargs']['test_paths'] harness_args = kwargs.copy() harness_args.update(suite['kwargs']) # Pass in the full suite name as defined in moztest/resolve.py in case # chunk-by-runtime is called, in which case runtime information for # specific mochitest suite has to be loaded. See Bug 1637463. harness_args.update({'suite_name': suite_name}) result = run_mochitest( self._mach_context, tests=tests, **harness_args) if result: overall = result # Halt tests on keyboard interrupt if result == -1: break # Only shutdown the logger if we created it if kwargs['log'].name == 'mach-mochitest': kwargs['log'].shutdown() return overall
def test(command_context, what, extra_args, **log_args): """Run tests from names or paths. mach test accepts arguments specifying which tests to run. Each argument can be: * The path to a test file * A directory containing tests * A test suite name * An alias to a test suite name (codes used on TreeHerder) When paths or directories are given, they are first resolved to test files known to the build system. If resolved tests belong to more than one test type/flavor/harness, the harness for each relevant type/flavor will be invoked. e.g. if you specify a directory with xpcshell and browser chrome mochitests, both harnesses will be invoked. Warning: `mach test` does not automatically re-build. Please remember to run `mach build` when necessary. EXAMPLES Run all test files in the devtools/client/shared/redux/middleware/xpcshell/ directory: `./mach test devtools/client/shared/redux/middleware/xpcshell/` The below command prints a short summary of results instead of the default more verbose output. Do not forget the - (minus sign) after --log-grouped! `./mach test --log-grouped - devtools/client/shared/redux/middleware/xpcshell/` """ from mozlog.commandline import setup_logging from mozlog.handlers import StreamHandler from moztest.resolve import get_suite_definition, TestResolver, TEST_SUITES resolver = command_context._spawn(TestResolver) run_suites, run_tests = resolver.resolve_metadata(what) if not run_suites and not run_tests: print(UNKNOWN_TEST) return 1 if log_args.get("debugger", None): import mozdebug if not mozdebug.get_debugger_info(log_args.get("debugger")): sys.exit(1) extra_args_debugger_notation = "=".join( ["--debugger", log_args.get("debugger")]) if extra_args: extra_args.append(extra_args_debugger_notation) else: extra_args = [extra_args_debugger_notation] # Create shared logger format_args = { "level": command_context._mach_context.settings["test"]["level"] } if not run_suites and len(run_tests) == 1: format_args["verbose"] = True format_args["compact"] = False default_format = command_context._mach_context.settings["test"]["format"] log = setup_logging("mach-test", log_args, {default_format: sys.stdout}, format_args) for handler in log.handlers: if isinstance(handler, StreamHandler): handler.formatter.inner.summary_on_shutdown = True status = None for suite_name in run_suites: suite = TEST_SUITES[suite_name] kwargs = suite["kwargs"] kwargs["log"] = log kwargs.setdefault("subsuite", None) if "mach_command" in suite: res = command_context._mach_context.commands.dispatch( suite["mach_command"], command_context._mach_context, argv=extra_args, **kwargs, ) if res: status = res buckets = {} for test in run_tests: key = (test["flavor"], test.get("subsuite", "")) buckets.setdefault(key, []).append(test) for (flavor, subsuite), tests in sorted(buckets.items()): _, m = get_suite_definition(flavor, subsuite) if "mach_command" not in m: substr = "-{}".format(subsuite) if subsuite else "" print(UNKNOWN_FLAVOR % (flavor, substr)) status = 1 continue kwargs = dict(m["kwargs"]) kwargs["log"] = log kwargs.setdefault("subsuite", None) res = command_context._mach_context.commands.dispatch( m["mach_command"], command_context._mach_context, argv=extra_args, test_objects=tests, **kwargs, ) if res: status = res log.shutdown() return status
def run(command_context, binary, params, debug, debugger, debugger_args): try: binpath = command_context.get_binary_path("geckodriver") except BinaryNotFoundException as e: command_context.log(logging.ERROR, "geckodriver", {"error": str(e)}, "ERROR: {error}") command_context.log( logging.INFO, "geckodriver", {}, "It looks like geckodriver isn't built. " "Add ac_add_options --enable-geckodriver to your " "mozconfig " "and run |./mach build| to build it.", ) return 1 args = [binpath] if params: args.extend(params) if binary is None: try: binary = command_context.get_binary_path("app") except BinaryNotFoundException as e: command_context.log(logging.ERROR, "geckodriver", {"error": str(e)}, "ERROR: {error}") command_context.log(logging.INFO, "geckodriver", {"help": e.help()}, "{help}") return 1 args.extend(["--binary", binary]) if debug or debugger or debugger_args: if "INSIDE_EMACS" in os.environ: command_context.log_manager.terminal_handler.setLevel( logging.WARNING) import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) if debugger: debuggerInfo = mozdebug.get_debugger_info(debugger, debugger_args) if not debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Parameters come from the CLI. We need to convert them before # their use. if debugger_args: from mozbuild import shellutil try: debugger_args = shellutil.split(debugger_args) except shellutil.MetaCharacterException as e: print( "The --debugger-args you passed require a real shell to parse them." ) print("(We can't handle the %r character.)" % e.char) return 1 # Prepend the debugger args. args = [debuggerInfo.path] + debuggerInfo.args + args return command_context.run_process(args=args, ensure_exit_code=False, pass_thru=True)
def run_mochitest_general(self, flavor=None, test_objects=None, resolve_tests=True, **kwargs): from mochitest_options import ALL_FLAVORS from mozlog.commandline import setup_logging from mozlog.handlers import StreamHandler from moztest.resolve import get_suite_definition # TODO: This is only strictly necessary while mochitest is using Python # 2 and can be removed once the command is migrated to Python 3. self.activate_virtualenv() buildapp = None for app in SUPPORTED_APPS: if conditions.is_buildapp_in(self, apps=[app]): buildapp = app break flavors = None if flavor: for fname, fobj in six.iteritems(ALL_FLAVORS): if flavor in fobj["aliases"]: if buildapp not in fobj["enabled_apps"]: continue flavors = [fname] break else: flavors = [ f for f, v in six.iteritems(ALL_FLAVORS) if buildapp in v["enabled_apps"] ] from mozbuild.controller.building import BuildDriver self._ensure_state_subdir_exists(".") test_paths = kwargs["test_paths"] kwargs["test_paths"] = [] if kwargs.get("debugger", None): import mozdebug if not mozdebug.get_debugger_info(kwargs.get("debugger")): sys.exit(1) mochitest = self._spawn(MochitestRunner) tests = [] if resolve_tests: tests = mochitest.resolve_tests(test_paths, test_objects, cwd=self._mach_context.cwd) if not kwargs.get("log"): # Create shared logger format_args = { "level": self._mach_context.settings["test"]["level"] } if len(tests) == 1: format_args["verbose"] = True format_args["compact"] = False default_format = self._mach_context.settings["test"]["format"] kwargs["log"] = setup_logging("mach-mochitest", kwargs, {default_format: sys.stdout}, format_args) for handler in kwargs["log"].handlers: if isinstance(handler, StreamHandler): handler.formatter.inner.summary_on_shutdown = True driver = self._spawn(BuildDriver) driver.install_tests() subsuite = kwargs.get("subsuite") if subsuite == "default": kwargs["subsuite"] = None suites = defaultdict(list) is_webrtc_tag_present = False unsupported = set() for test in tests: # Check if we're running a webrtc test so we can enable webrtc # specific test logic later if needed. if "webrtc" in test.get("tags", ""): is_webrtc_tag_present = True # Filter out non-mochitests and unsupported flavors. if test["flavor"] not in ALL_FLAVORS: continue key = (test["flavor"], test.get("subsuite", "")) if test["flavor"] not in flavors: unsupported.add(key) continue if subsuite == "default": # "--subsuite default" means only run tests that don't have a subsuite if test.get("subsuite"): unsupported.add(key) continue elif subsuite and test.get("subsuite", "") != subsuite: unsupported.add(key) continue suites[key].append(test) # Only webrtc mochitests in the media suite need the websocketprocessbridge. if ("mochitest", "media") in suites and is_webrtc_tag_present: req = os.path.join( "testing", "tools", "websocketprocessbridge", "websocketprocessbridge_requirements_3.txt", ) self.virtualenv_manager.activate() self.virtualenv_manager.install_pip_requirements( req, require_hashes=False) # sys.executable is used to start the websocketprocessbridge, though for some # reason it doesn't get set when calling `activate_this.py` in the virtualenv. sys.executable = self.virtualenv_manager.python_path # This is a hack to introduce an option in mach to not send # filtered tests to the mochitest harness. Mochitest harness will read # the master manifest in that case. if not resolve_tests: for flavor in flavors: key = (flavor, kwargs.get("subsuite")) suites[key] = [] if not suites: # Make it very clear why no tests were found if not unsupported: print( TESTS_NOT_FOUND.format("\n".join( sorted(list(test_paths or test_objects))))) return 1 msg = [] for f, s in unsupported: fobj = ALL_FLAVORS[f] apps = fobj["enabled_apps"] name = fobj["aliases"][0] if s: name = "{} --subsuite {}".format(name, s) if buildapp not in apps: reason = "requires {}".format(" or ".join(apps)) else: reason = "excluded by the command line" msg.append(" mochitest -f {} ({})".format(name, reason)) print( SUPPORTED_TESTS_NOT_FOUND.format(buildapp, "\n".join(sorted(msg)))) return 1 if buildapp == "android": from mozrunner.devices.android_device import ( verify_android_device, InstallIntent, ) app = kwargs.get("app") if not app: app = "org.mozilla.geckoview.test" device_serial = kwargs.get("deviceSerial") install = (InstallIntent.NO if kwargs.get("no_install") else InstallIntent.YES) # verify installation verify_android_device( self, install=install, xre=False, network=True, app=app, device_serial=device_serial, ) run_mochitest = mochitest.run_android_test else: run_mochitest = mochitest.run_desktop_test overall = None for (flavor, subsuite), tests in sorted(suites.items()): suite_name, suite = get_suite_definition(flavor, subsuite) if "test_paths" in suite["kwargs"]: del suite["kwargs"]["test_paths"] harness_args = kwargs.copy() harness_args.update(suite["kwargs"]) # Pass in the full suite name as defined in moztest/resolve.py in case # chunk-by-runtime is called, in which case runtime information for # specific mochitest suite has to be loaded. See Bug 1637463. harness_args.update({"suite_name": suite_name}) result = run_mochitest(self._mach_context, tests=tests, **harness_args) if result: overall = result # Halt tests on keyboard interrupt if result == -1: break # Only shutdown the logger if we created it if kwargs["log"].name == "mach-mochitest": kwargs["log"].shutdown() return overall
def test(self, what, extra_args, **log_args): """Run tests from names or paths. mach test accepts arguments specifying which tests to run. Each argument can be: * The path to a test file * A directory containing tests * A test suite name * An alias to a test suite name (codes used on TreeHerder) If no input is provided, tests will be run based on files changed in the local tree. Relevant tests, tags, or flavors are determined by IMPACTED_TESTS annotations in moz.build files relevant to the changed files. When paths or directories are given, they are first resolved to test files known to the build system. If resolved tests belong to more than one test type/flavor/harness, the harness for each relevant type/flavor will be invoked. e.g. if you specify a directory with xpcshell and browser chrome mochitests, both harnesses will be invoked. """ from mozlog.commandline import setup_logging from mozlog.handlers import StreamHandler from moztest.resolve import get_suite_definition, TestResolver, TEST_SUITES resolver = self._spawn(TestResolver) run_suites, run_tests = resolver.resolve_metadata(what) if not run_suites and not run_tests: print(UNKNOWN_TEST) return 1 if log_args.get('debugger', None): import mozdebug if not mozdebug.get_debugger_info(log_args.get('debugger')): sys.exit(1) extra_args_debugger_notation = '='.join( ['--debugger', log_args.get('debugger')]).encode('ascii') if extra_args: extra_args.append(extra_args_debugger_notation) else: extra_args = [extra_args_debugger_notation] # Create shared logger format_args = {'level': self._mach_context.settings['test']['level']} if not run_suites and len(run_tests) == 1: format_args['verbose'] = True format_args['compact'] = False default_format = self._mach_context.settings['test']['format'] log = setup_logging('mach-test', log_args, {default_format: sys.stdout}, format_args) for handler in log.handlers: if isinstance(handler, StreamHandler): handler.formatter.inner.summary_on_shutdown = True status = None for suite_name in run_suites: suite = TEST_SUITES[suite_name] kwargs = suite['kwargs'] kwargs['log'] = log if 'mach_command' in suite: res = self._mach_context.commands.dispatch( suite['mach_command'], self._mach_context, argv=extra_args, **kwargs) if res: status = res buckets = {} for test in run_tests: key = (test['flavor'], test.get('subsuite', '')) buckets.setdefault(key, []).append(test) for (flavor, subsuite), tests in sorted(buckets.items()): _, m = get_suite_definition(flavor, subsuite) if 'mach_command' not in m: substr = '-{}'.format(subsuite) if subsuite else '' print(UNKNOWN_FLAVOR % (flavor, substr)) status = 1 continue kwargs = dict(m['kwargs']) kwargs['log'] = log res = self._mach_context.commands.dispatch(m['mach_command'], self._mach_context, argv=extra_args, test_objects=tests, **kwargs) if res: status = res log.shutdown() return status
def check_args(kwargs): set_from_config(kwargs) if kwargs["product"] is None: kwargs["product"] = "firefox" if kwargs["manifest_update"] is None: kwargs["manifest_update"] = True if "sauce" in kwargs["product"]: kwargs["pause_after_test"] = False if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["test_groups_file"] is not None: if kwargs["run_by_dir"] is not False: print("Can't pass --test-groups and --run-by-dir") sys.exit(1) if not os.path.exists(kwargs["test_groups_file"]): print("--test-groups file %s not found" % kwargs["test_groups_file"]) sys.exit(1) if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print("Binary path %s does not exist" % kwargs["binary"], file=sys.stderr) sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x: os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x: os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print("openssl-binary argument missing or not a valid executable", file=sys.stderr) sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs[ "product"] == "firefox" and kwargs["certutil_binary"]: path = exe_path(kwargs["certutil_binary"]) if path is None: print("certutil-binary argument missing or not a valid executable", file=sys.stderr) sys.exit(1) kwargs["certutil_binary"] = path if kwargs['extra_prefs']: missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) if missing: print("Preferences via --setpref must be in key=value format", file=sys.stderr) sys.exit(1) kwargs['extra_prefs'] = [ tuple(prefarg.split('=', 1)) for prefarg in kwargs['extra_prefs'] ] if kwargs["reftest_internal"] is None: kwargs["reftest_internal"] = True if kwargs["reftest_screenshot"] is None: kwargs["reftest_screenshot"] = "unexpected" if not kwargs[ "debug_test"] else "always" if kwargs["enable_webrender"] is None: kwargs["enable_webrender"] = False if kwargs["preload_browser"] is None: # Default to preloading a gecko instance if we're only running a single process kwargs["preload_browser"] = kwargs["processes"] == 1 return kwargs
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 check_args(kwargs): set_from_config(kwargs) if kwargs["product"] is None: kwargs["product"] = "firefox" if "sauce" in kwargs["product"]: kwargs["pause_after_test"] = False if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "dir_hash" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print >> sys.stderr, "Binary path %s does not exist" % kwargs["binary"] sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x:os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print >> sys.stderr, "openssl-binary argument missing or not a valid executable" sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox" and kwargs["certutil_binary"]: path = exe_path(kwargs["certutil_binary"]) if path is None: print >> sys.stderr, "certutil-binary argument missing or not a valid executable" sys.exit(1) kwargs["certutil_binary"] = path if kwargs['extra_prefs']: missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs']) if missing: print >> sys.stderr, "Preferences via --setpref must be in key=value format" sys.exit(1) kwargs['extra_prefs'] = [tuple(prefarg.split('=', 1)) for prefarg in kwargs['extra_prefs']] if kwargs["reftest_internal"] is None: # Default to the internal reftest implementation on Linux and OSX kwargs["reftest_internal"] = sys.platform.startswith("linux") or sys.platform.startswith("darwin") return kwargs
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, browserhtml=False): env = self.build_env() env["RUST_BACKTRACE"] = "1" if android is None: android = self.config["build"]["android"] if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop com.mozilla.servo", "echo servo >/sdcard/servo/android_params" ] for param in params: script += [ "echo '%s' >>/sdcard/servo/android_params" % param.replace("'", "\\'") ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", "exit" ] shell = subprocess.Popen(["adb", "shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [self.get_binary_path(release, dev)] # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) except (OSError, subprocess.CalledProcessError): pass else: command = rustCommand # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) elif browserhtml: browserhtml_path = find_dep_path_newest('browserhtml', args[0]) if browserhtml_path is None: print("Could not find browserhtml package; perhaps you haven't built Servo.") return 1 args = args + ['-w', '-b', '--pref', 'dom.mozbrowser.enabled', path.join(browserhtml_path, 'out', 'index.html')] args = args + params else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, browserhtml=False): env = self.build_env() env["RUST_BACKTRACE"] = "1" if android is None: android = self.config["build"]["android"] if android: if debug: print("Android on-device debugging is not supported by mach yet. See") print("https://github.com/servo/servo/wiki/Building-for-Android#debugging-on-device") return script = [ "am force-stop com.mozilla.servo", "echo servo >/sdcard/servo/android_params" ] for param in params: script += [ "echo '%s' >>/sdcard/servo/android_params" % param.replace("'", "\\'") ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", "exit" ] shell = subprocess.Popen(["adb", "shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() args = [self.get_binary_path(release, dev)] # Borrowed and modified from: # http://hg.mozilla.org/mozilla-central/file/c9cfa9b91dea/python/mozbuild/mozbuild/mach_commands.py#l883 if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info(debugger) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 command = self.debuggerInfo.path if debugger == 'gdb' or debugger == 'lldb': rustCommand = 'rust-' + debugger try: subprocess.check_call([rustCommand, '--version'], env=env, stdout=open(os.devnull, 'w')) command = rustCommand except (OSError, subprocess.CalledProcessError): pass # Prepend the debugger args. args = ([command] + self.debuggerInfo.args + args + params) elif browserhtml: browserhtml_path = find_dep_path_newest('browserhtml', args[0]) if browserhtml_path is None: print("Could not find browserhtml package; perhaps you haven't built Servo.") return 1 args = args + ['-w', '-b', '--pref', 'dom.mozbrowser.enabled', path.join(browserhtml_path, 'out', 'index.html')] args = args + params else: args = args + params try: check_call(args, env=env) except subprocess.CalledProcessError as e: print("Servo exited with return value %d" % e.returncode) return e.returncode except OSError as e: if e.errno == 2: print("Servo Binary can't be found! Run './mach build'" " and try again!") else: raise e
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(self, params, remote, background, noprofile, debug, debugger, debugparams, slowscript, dmd, sample_below, max_frames, show_dump_stats, mode): try: binpath = self.get_binary_path('app') except Exception as e: print("It looks like your program isn't built.", "You can run |mach build| to build it.") print(e) return 1 args = [binpath] if params: args.extend(params) if not remote: args.append('-no-remote') if not background and sys.platform == 'darwin': args.append('-foreground') if '-profile' not in params and '-P' not in params and not noprofile: path = os.path.join(self.topobjdir, 'tmp', 'scratch_user') if not os.path.isdir(path): os.makedirs(path) args.append('-profile') args.append(path) extra_env = {} if debug: import mozdebug if not debugger: # No debugger name was provided. Look for the default ones on # current OS. debugger = mozdebug.get_default_debugger_name( mozdebug.DebuggerSearch.KeepLooking) self.debuggerInfo = mozdebug.get_debugger_info( debugger, debugparams) if not self.debuggerInfo: print("Could not find a suitable debugger in your PATH.") return 1 # Parameters come from the CLI. We need to convert them before # their use. if debugparams: import pymake.process argv, badchar = pymake.process.clinetoargv( debugparams, os.getcwd()) if badchar: print( "The --debugparams you passed require a real shell to parse them." ) print("(We can't handle the %r character.)" % (badchar, )) return 1 debugparams = argv if not slowscript: extra_env['JS_DISABLE_SLOW_SCRIPT_SIGNALS'] = '1' extra_env['MOZ_CRASHREPORTER_DISABLE'] = '1' # Prepend the debugger args. args = [self.debuggerInfo.path] + self.debuggerInfo.args + args if dmd: dmd_params = [] if sample_below: dmd_params.append('--sample-below=' + sample_below) if max_frames: dmd_params.append('--max-frames=' + max_frames) if show_dump_stats: dmd_params.append('--show-dump-stats=yes') if mode: dmd_params.append('--mode=' + mode) if dmd_params: dmd_env_var = " ".join(dmd_params) else: dmd_env_var = "1" bin_dir = os.path.dirname(binpath) lib_name = self.substs['DLL_PREFIX'] + 'dmd' + self.substs[ 'DLL_SUFFIX'] dmd_lib = os.path.join(bin_dir, lib_name) if not os.path.exists(dmd_lib): print("Please build with |--enable-dmd| to use DMD.") return 1 env_vars = { "Darwin": { "DYLD_INSERT_LIBRARIES": dmd_lib, "LD_LIBRARY_PATH": bin_dir, "DMD": dmd_env_var, }, "Linux": { "LD_PRELOAD": dmd_lib, "LD_LIBRARY_PATH": bin_dir, "DMD": dmd_env_var, }, "WINNT": { "MOZ_REPLACE_MALLOC_LIB": dmd_lib, "DMD": dmd_env_var, }, } extra_env.update(env_vars.get(self.substs['OS_ARCH'], {})) return self.run_process(args=args, ensure_exit_code=False, pass_thru=True, append_env=extra_env)
def check_args(kwargs): set_from_config(kwargs) for test_paths in kwargs["test_paths"].itervalues(): if not ("tests_path" in test_paths and "metadata_path" in test_paths): print "Fatal: must specify both a test path and metadata path" sys.exit(1) for key, path in test_paths.iteritems(): name = key.split("_", 1)[0] if not os.path.exists(path): print "Fatal: %s path %s does not exist" % (name, path) sys.exit(1) if not os.path.isdir(path): print "Fatal: %s path %s is not a directory" % (name, path) sys.exit(1) if kwargs["product"] is None: kwargs["product"] = "firefox" if kwargs["test_list"]: if kwargs["include"] is not None: kwargs["include"].extend(kwargs["test_list"]) else: kwargs["include"] = kwargs["test_list"] if kwargs["run_info"] is None: kwargs["run_info"] = kwargs["config_path"] if kwargs["this_chunk"] > 1: require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"]) if kwargs["chunk_type"] is None: if kwargs["total_chunks"] > 1: kwargs["chunk_type"] = "equal_time" else: kwargs["chunk_type"] = "none" if kwargs["processes"] is None: kwargs["processes"] = 1 if kwargs["debugger"] is not None: import mozdebug if kwargs["debugger"] == "__default__": kwargs["debugger"] = mozdebug.get_default_debugger_name() debug_info = mozdebug.get_debugger_info(kwargs["debugger"], kwargs["debugger_args"]) if debug_info and debug_info.interactive: if kwargs["processes"] != 1: kwargs["processes"] = 1 kwargs["no_capture_stdio"] = True kwargs["debug_info"] = debug_info else: kwargs["debug_info"] = None if kwargs["binary"] is not None: if not os.path.exists(kwargs["binary"]): print >> sys.stderr, "Binary path %s does not exist" % kwargs["binary"] sys.exit(1) if kwargs["ssl_type"] is None: if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]): kwargs["ssl_type"] = "pregenerated" elif exe_path(kwargs["openssl_binary"]) is not None: kwargs["ssl_type"] = "openssl" else: kwargs["ssl_type"] = "none" if kwargs["ssl_type"] == "pregenerated": require_arg(kwargs, "ca_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_cert_path", lambda x:os.path.exists(x)) require_arg(kwargs, "host_key_path", lambda x:os.path.exists(x)) elif kwargs["ssl_type"] == "openssl": path = exe_path(kwargs["openssl_binary"]) if path is None: print >> sys.stderr, "openssl-binary argument missing or not a valid executable" sys.exit(1) kwargs["openssl_binary"] = path if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox": path = exe_path(kwargs["certutil_binary"]) if path is None: print >> sys.stderr, "certutil-binary argument missing or not a valid executable" sys.exit(1) kwargs["certutil_binary"] = path return kwargs
def runSerialTests(self, manifests, options, cmdargs=None): debuggerInfo = None if options.debugger: debuggerInfo = mozdebug.get_debugger_info( options.debugger, options.debuggerArgs, options.debuggerInteractive) def run(**kwargs): if kwargs.get("tests"): self.lastTest = kwargs["tests"][-1]["identifier"] if not isinstance(self.lastTest, string_types): 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 if not self.run_by_manifest: return run() tests = self.getActiveTests(manifests, options) tests_by_manifest = defaultdict(list) ids_by_manifest = defaultdict(list) for t in tests: tests_by_manifest[t["manifest"]].append(t) test_id = t["identifier"] if not isinstance(test_id, string_types): test_id = " ".join(test_id) ids_by_manifest[t["manifestID"]].append(test_id) self.log.suite_start(ids_by_manifest, name=options.suite) overall = 0 for manifest, tests in tests_by_manifest.items(): self.log.info("Running tests in {}".format(manifest)) status = run(tests=tests) overall = overall or status self.log.suite_end(extra={"results": self.outputHandler.results}) return overall