예제 #1
0
    def killNamedOrphans(self, pname):
        """ Kill orphan processes matching the given command name """
        self.log.info("Checking for orphan %s processes..." % pname)

        def _psInfo(line):
            if pname in line:
                self.log.info(line)

        process = mozprocess.ProcessHandler(['ps', '-f'],
                                            processOutputLine=_psInfo)
        process.run()
        process.wait()

        def _psKill(line):
            parts = line.split()
            if len(parts) == 3 and parts[0].isdigit():
                pid = int(parts[0])
                if parts[2] == pname and parts[1] == '1':
                    self.log.info("killing %s orphan with pid %d" %
                                  (pname, pid))
                    try:
                        os.kill(pid, getattr(signal, "SIGKILL",
                                             signal.SIGTERM))
                    except Exception as e:
                        self.log.info("Failed to kill process %d: %s" %
                                      (pid, str(e)))

        process = mozprocess.ProcessHandler(['ps', '-o', 'pid,ppid,comm'],
                                            processOutputLine=_psKill)
        process.run()
        process.wait()
예제 #2
0
    def run_one_test(self, prog, env, symbols_path=None, interactive=False,
                     timeout_factor=1):
        """
        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.
        * symbols_path: A path to a directory containing Breakpad-formatted
                        symbol files for producing stack traces on crash.
        * timeout_factor: An optional test-specific timeout multiplier.

        Return True if the program exits with a zero status, False otherwise.
        """
        basename = os.path.basename(prog)
        self.log.test_start(basename)
        with mozfile.TemporaryDirectory() as tempdir:
            if interactive:
                # For tests run locally, via mach, print output directly
                proc = mozprocess.ProcessHandler([prog],
                                                 cwd=tempdir,
                                                 env=env,
                                                 storeOutput=False)
            else:
                proc = mozprocess.ProcessHandler([prog],
                                                 cwd=tempdir,
                                                 env=env,
                                                 storeOutput=True,
                                                 processOutputLine=lambda _: None)
            # 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.
            test_timeout = CPPUnitTests.TEST_PROC_TIMEOUT * timeout_factor
            proc.run(timeout=test_timeout,
                     outputTimeout=CPPUnitTests.TEST_PROC_NO_OUTPUT_TIMEOUT)
            proc.wait()
            if proc.output:
                if self.fix_stack:
                    procOutput = [self.fix_stack(l) for l in proc.output]
                else:
                    procOutput = proc.output

                output = "\n%s" % "\n".join(procOutput)
                self.log.process_output(proc.pid, output, command=[prog])
            if proc.timedOut:
                message = "timed out after %d seconds" % CPPUnitTests.TEST_PROC_TIMEOUT
                self.log.test_end(basename, status='TIMEOUT', expected='PASS',
                                  message=message)
                return False
            if mozcrash.check_for_crashes(tempdir, symbols_path,
                                          test_name=basename):
                self.log.test_end(basename, status='CRASH', expected='PASS')
                return False
            result = proc.proc.returncode == 0
            if not result:
                self.log.test_end(basename, status='FAIL', expected='PASS',
                                  message=("test failed with return code %d" %
                                           proc.proc.returncode))
            else:
                self.log.test_end(basename, status='PASS', expected='PASS')
            return result
    def _run(self, block):
        self._cmd = self.make_command()
        self._proc = mozprocess.ProcessHandler(
            self._cmd,
            processOutputLine=self.on_output,
            env=self.env,
            storeOutput=False)

        try:
            self._proc.run()
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise IOError(
                    "WebDriver HTTP server executable not found: %s" %
                    self.binary)
            raise

        self.logger.debug("Waiting for server to become accessible: %s" %
                          self.url)
        try:
            wait_for_service((self.host, self.port))
        except:
            self.logger.error("WebDriver HTTP server was not accessible "
                              "within the timeout:\n%s" %
                              traceback.format_exc())
            raise

        if block:
            self._proc.wait()
예제 #4
0
    def run_one_test(self, prog, env, symbols_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.
        * symbols_path: A path to a directory containing Breakpad-formatted
                        symbol files for producing stack traces on crash.

        Return True if the program exits with a zero status, False otherwise.
        """
        basename = os.path.basename(prog)
        log.info("Running test %s", basename)
        with TemporaryDirectory() as tempdir:
            proc = mozprocess.ProcessHandler([prog], cwd=tempdir, env=env)
            #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=CPPUnitTests.TEST_PROC_TIMEOUT,
                     outputTimeout=CPPUnitTests.TEST_PROC_NO_OUTPUT_TIMEOUT)
            proc.wait()
            if proc.timedOut:
                log.testFail("%s | timed out after %d seconds", basename,
                             CPPUnitTests.TEST_PROC_TIMEOUT)
                return False
            if mozcrash.check_for_crashes(tempdir,
                                          symbols_path,
                                          test_name=basename):
                log.testFail("%s | test crashed", basename)
                return False
            result = proc.proc.returncode == 0
            if not result:
                log.testFail("%s | test failed with return code %d", basename,
                             proc.proc.returncode)
            return result
예제 #5
0
    def _run_server(self, group_metadata, **kwargs):
        cmd = self.make_command()
        self._output_handler = self.create_output_handler(cmd)

        self._proc = mozprocess.ProcessHandler(
            cmd,
            processOutputLine=self._output_handler,
            env=self.env,
            storeOutput=False)

        self.logger.debug("Starting WebDriver: %s" % ' '.join(cmd))
        try:
            self._proc.run()
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise IOError("WebDriver executable not found: %s" %
                              self.webdriver_binary)
            raise
        self._output_handler.after_process_start(self._proc.pid)

        try:
            wait_for_service(self.logger, self.host, self.port)
        except Exception:
            self.logger.error("WebDriver was not accessible "
                              f"within the timeout:\n{traceback.format_exc()}")
            raise
        self._output_handler.start(group_metadata=group_metadata, **kwargs)
        self.logger.debug("_run complete")
예제 #6
0
    def run_test(self, suite, groups, temp_dir):
        logger.info('Running suite %s' % suite)

        try:
            cmd, output_files = self.build_command(suite, groups, temp_dir)

            logger.debug(cmd)
            logger.debug(output_files)

            env = dict(os.environ)
            env['PYTHONUNBUFFERED'] = '1'
            proc = mozprocess.ProcessHandler(cmd, env=env)
            logger.debug("Process '%s' is running" % " ".join(cmd))
            #TODO: move timeout handling to here instead of each test?
            proc.run()
            proc.wait()
            logger.debug("Process finished")

        except Exception:
            logger.critical("Error running suite %s:\n%s" %
                            (suite, traceback.format_exc()))
            raise
        finally:
            try:
                proc.kill()
            except:
                pass

        return output_files
    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
예제 #8
0
 def start(self):
     self.cmd = [
         self.binary,
         cmd_arg("port", str(self.webdriver_port)),
         cmd_arg("url-base", "wd/url")
     ]
     self.proc = mozprocess.ProcessHandler(self.cmd,
                                           processOutputLine=self.on_output)
     self.logger.debug("Starting chromedriver")
     self.proc.run()
예제 #9
0
    def _run(self):
        try:
            # TODO: adb logcat -c fail randomly with message
            # "failed to clear the 'main' log"
            self.browser.clear_log()
        except subprocess.CalledProcessError:
            self.logger.error("Failed to clear logcat buffer")

        self._cmd = self.browser.logcat_cmd()
        self._proc = mozprocess.ProcessHandler(
            self._cmd, processOutputLine=self.on_output, storeOutput=False)
        self._proc.run()
예제 #10
0
    def run_test(self, suite, groups, temp_dir):
        logger.info('Running suite %s' % suite)

        def on_output(line):
            written = False
            if line.startswith("{"):
                try:
                    data = json.loads(line.strip())
                    if "action" in data:
                        sub_logger.log_raw(data)
                        written = True
                except ValueError:
                    pass
            if not written:
                logger.process_output(proc.pid,
                                      line.decode("utf8", "replace"),
                                      command=" ".join(cmd))

        try:
            cmd, output_files, structured_path = self.build_command(
                suite, groups, temp_dir)

            logger.debug(cmd)
            logger.debug(output_files)

            env = dict(os.environ)
            env['PYTHONUNBUFFERED'] = '1'
            proc = mozprocess.ProcessHandler(cmd,
                                             env=env,
                                             processOutputLine=on_output)
            logger.debug("Process '%s' is running" % " ".join(cmd))
            #TODO: move timeout handling to here instead of each test?
            with open(structured_path, "w") as structured_log:
                sub_logger = structuredlog.StructuredLogger(suite)
                sub_logger.add_handler(stdio_handler)
                sub_logger.add_handler(
                    handlers.StreamHandler(structured_log,
                                           formatters.JSONFormatter()))
                proc.run()
                proc.wait()
            logger.debug("Process finished")

        except Exception:
            logger.error("Error running suite %s:\n%s" %
                         (suite, traceback.format_exc()))
            raise
        finally:
            try:
                proc.kill()
            except:
                pass

        return output_files, structured_path
예제 #11
0
    def run_gtest(self, prog, xre_path, symbols_path=None, cwd=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.
        * symbols_path: A path to a directory containing Breakpad-formatted
                        symbol files for producing stack traces on crash.

        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)

        proc = mozprocess.ProcessHandler([prog, "-unittest"], cwd=cwd, env=env)
        #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:
            log.testFail("gtest | timed out after %d seconds",
                         GTests.TEST_PROC_TIMEOUT)
            return False
        if mozcrash.check_for_crashes(os.getcwd(),
                                      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
예제 #12
0
    def start(self):
        self.proc = mozprocess.ProcessHandler(self.cmd,
                                              processOutputLine=self.on_output)
        try:
            self.proc.run()
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise IOError("chromedriver executable not found: %s" %
                              self.binary)
            raise

        self.logger.debug("Waiting for server to become accessible: %s" %
                          self.url)
        surl = urlparse.urlparse(self.url)
        addr = (surl.hostname, surl.port)
        try:
            wait_service(addr)
        except:
            self.logger.error(
                "Server was not accessible within the timeout:\n%s" %
                traceback.format_exc())
            raise
        else:
            self.logger.info("Server listening on port %i" % self.port)
예제 #13
0
    def _run(self, block, output_handler_kwargs, output_handler_start_kwargs):
        if output_handler_kwargs is None:
            output_handler_kwargs = {}
        if output_handler_start_kwargs is None:
            output_handler_start_kwargs = {}
        self._cmd = self.make_command()
        self._output_handler = self.output_handler_cls(self.logger, self._cmd,
                                                       **output_handler_kwargs)
        self._proc = mozprocess.ProcessHandler(
            self._cmd,
            processOutputLine=self._output_handler,
            env=self.env,
            storeOutput=False)

        self.logger.debug("Starting WebDriver: %s" % ' '.join(self._cmd))
        try:
            self._proc.run()
        except OSError as e:
            if e.errno == errno.ENOENT:
                raise IOError("WebDriver executable not found: %s" %
                              self.binary)
            raise
        self._output_handler.after_process_start(self._proc.pid)

        self.logger.debug("Waiting for WebDriver to become accessible: %s" %
                          self.url)
        try:
            wait_for_service((self.host, self.port))
        except Exception:
            self.logger.error("WebDriver was not accessible "
                              "within the timeout:\n%s" %
                              traceback.format_exc())
            raise
        self._output_handler.start(**output_handler_start_kwargs)
        if block:
            self._proc.wait()
예제 #14
0
def run_one_test(prog, env, symbols_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.
    * symbols_path: A path to a directory containing Breakpad-formatted
                    symbol files for producing stack traces on crash.

    Return True if the program exits with a zero status, False otherwise.
    """
    basename = os.path.basename(prog)
    log.info("Running test %s", basename)
    with TemporaryDirectory() as tempdir:
        proc = mozprocess.ProcessHandler([prog], cwd=tempdir, env=env)
        proc.run()
        timeout = 300
        proc.processOutput(timeout=timeout)
        if proc.timedOut:
            log.testFail("%s | timed out after %d seconds", basename, timeout)
            return False
        proc.waitForFinish(timeout=timeout)
        if proc.timedOut:
            log.testFail("%s | timed out after %d seconds", basename, timeout)
            return False
        if mozcrash.check_for_crashes(tempdir,
                                      symbols_path,
                                      test_name=basename):
            log.testFail("%s | test crashed", basename)
            return False
        result = proc.proc.returncode == 0
        if not result:
            log.testFail("%s | test failed with return code %d", basename,
                         proc.proc.returncode)
        return result
예제 #15
0
    def get_browser_meta(self):
        """Returns the browser name and version in a tuple (name, version).

        On desktop, we use mozversion but a fallback method also exists
        for non-firefox browsers, where mozversion is known to fail. The
        methods are OS-specific, with windows being the outlier.
        """
        browser_name = None
        browser_version = None

        try:
            meta = mozversion.get_version(binary=self.config["binary"])
            browser_name = meta.get("application_name")
            browser_version = meta.get("application_version")
        except Exception as e:
            LOG.warning(
                "Failed to get browser meta data through mozversion: %s-%s" %
                (e.__class__.__name__, e))
            LOG.info("Attempting to get version through fallback method...")

            # Fall-back method to get browser version on desktop
            try:
                if ("linux" in self.config["platform"]
                        or "mac" in self.config["platform"]):
                    command = [self.config["binary"], "--version"]
                    proc = mozprocess.ProcessHandler(command)
                    proc.run(timeout=10, outputTimeout=10)
                    proc.wait()

                    bmeta = proc.output
                    meta_re = re.compile(r"([A-z\s]+)\s+([\w.]*)")
                    if len(bmeta) != 0:
                        match = meta_re.match(bmeta[0].decode("utf-8"))
                        if match:
                            browser_name = self.config["app"]
                            browser_version = match.group(2)
                    else:
                        LOG.info("Couldn't get browser version and name")
                else:
                    # On windows we need to use wimc to get the version
                    command = r'wmic datafile where name="{0}"'.format(
                        self.config["binary"].replace("\\", r"\\"))
                    bmeta = subprocess.check_output(command)

                    meta_re = re.compile(r"\s+([\d.a-z]+)\s+")
                    match = meta_re.findall(bmeta.decode("utf-8"))
                    if len(match) > 0:
                        browser_name = self.config["app"]
                        browser_version = match[-1]
                    else:
                        LOG.info("Couldn't get browser version and name")
            except Exception as e:
                LOG.warning(
                    "Failed to get browser meta data through fallback method: %s-%s"
                    % (e.__class__.__name__, e))

        if not browser_name:
            LOG.warning("Could not find a browser name")
        else:
            LOG.info("Browser name: %s" % browser_name)

        if not browser_version:
            LOG.warning("Could not find a browser version")
        else:
            LOG.info("Browser version: %s" % browser_version)

        return (browser_name, browser_version)