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
Exemple #3
0
    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, 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
Exemple #5
0
    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 = {}
Exemple #6
0
    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
Exemple #9
0
    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
Exemple #10
0
    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
Exemple #11
0
    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
Exemple #12
0
    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
Exemple #13
0
 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
Exemple #14
0
    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
Exemple #15
0
    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
Exemple #16
0
 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)
Exemple #17
0
    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
Exemple #18
0
 def __init__(self, log, utilityPath, symbolsPath=None):
     self.stack_fixer_function = get_stack_fixer_function(
         utilityPath, symbolsPath)
     self.log = log
Exemple #19
0
    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
Exemple #20
0
 def __init__(self, log, utilityPath, symbolsPath=None):
     self.stack_fixer_function = get_stack_fixer_function(utilityPath, symbolsPath)
     self.log = log
Exemple #21
0
 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)
Exemple #22
0
    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
Exemple #23
0
    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
Exemple #24
0
 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
Exemple #25
0
 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
Exemple #26
0
 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)
Exemple #27
0
    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