testing/gtest/rungtests.py

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/testing/gtest/rungtests.py	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,124 @@
     1.4 +#!/usr/bin/env python
     1.5 +#
     1.6 +# This Source Code Form is subject to the terms of the Mozilla Public
     1.7 +# License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 +# file, You can obtain one at http://mozilla.org/MPL/2.0/.
     1.9 +
    1.10 +from __future__ import with_statement
    1.11 +import sys, os
    1.12 +from optparse import OptionParser
    1.13 +import mozprocess, mozinfo, mozlog, mozcrash
    1.14 +
    1.15 +log = mozlog.getLogger('gtest')
    1.16 +
    1.17 +class GTests(object):
    1.18 +    # Time (seconds) to wait for test process to complete
    1.19 +    TEST_PROC_TIMEOUT = 1200
    1.20 +    # Time (seconds) in which process will be killed if it produces no output.
    1.21 +    TEST_PROC_NO_OUTPUT_TIMEOUT = 300
    1.22 +
    1.23 +    def run_gtest(self, prog, xre_path, symbols_path=None):
    1.24 +        """
    1.25 +        Run a single C++ unit test program.
    1.26 +
    1.27 +        Arguments:
    1.28 +        * prog: The path to the test program to run.
    1.29 +        * env: The environment to use for running the program.
    1.30 +        * symbols_path: A path to a directory containing Breakpad-formatted
    1.31 +                        symbol files for producing stack traces on crash.
    1.32 +
    1.33 +        Return True if the program exits with a zero status, False otherwise.
    1.34 +        """
    1.35 +        self.xre_path = xre_path
    1.36 +        env = self.build_environment()
    1.37 +        log.info("Running gtest")
    1.38 +        proc = mozprocess.ProcessHandler([prog, "-unittest"],
    1.39 +                                         cwd=os.getcwd(),
    1.40 +                                         env=env)
    1.41 +        #TODO: After bug 811320 is fixed, don't let .run() kill the process,
    1.42 +        # instead use a timeout in .wait() and then kill to get a stack.
    1.43 +        proc.run(timeout=GTests.TEST_PROC_TIMEOUT,
    1.44 +                 outputTimeout=GTests.TEST_PROC_NO_OUTPUT_TIMEOUT)
    1.45 +        proc.wait()
    1.46 +        if proc.timedOut:
    1.47 +            log.testFail("gtest | timed out after %d seconds", GTests.TEST_PROC_TIMEOUT)
    1.48 +            return False
    1.49 +        if mozcrash.check_for_crashes(os.getcwd(), symbols_path, test_name="gtest"):
    1.50 +            # mozcrash will output the log failure line for us.
    1.51 +            return False
    1.52 +        result = proc.proc.returncode == 0
    1.53 +        if not result:
    1.54 +            log.testFail("gtest | test failed with return code %d", proc.proc.returncode)
    1.55 +        return result
    1.56 +
    1.57 +    def build_core_environment(self, env = {}):
    1.58 +        """
    1.59 +        Add environment variables likely to be used across all platforms, including remote systems.
    1.60 +        """
    1.61 +        env["MOZILLA_FIVE_HOME"] = self.xre_path
    1.62 +        env["MOZ_XRE_DIR"] = self.xre_path
    1.63 +        env["XPCOM_DEBUG_BREAK"] = "stack-and-abort"
    1.64 +        env["MOZ_CRASHREPORTER_NO_REPORT"] = "1"
    1.65 +        env["MOZ_CRASHREPORTER"] = "1"
    1.66 +        env["MOZ_RUN_GTEST"] = "1"
    1.67 +        # Normally we run with GTest default output, override this to use the TBPL test format.
    1.68 +        env["MOZ_TBPL_PARSER"] = "1"
    1.69 +        return env
    1.70 +
    1.71 +    def build_environment(self):
    1.72 +        """
    1.73 +        Create and return a dictionary of all the appropriate env variables and values.
    1.74 +        On a remote system, we overload this to set different values and are missing things like os.environ and PATH.
    1.75 +        """
    1.76 +        if not os.path.isdir(self.xre_path):
    1.77 +            raise Exception("xre_path does not exist: %s", self.xre_path)
    1.78 +        env = dict(os.environ)
    1.79 +        env = self.build_core_environment(env)
    1.80 +        pathvar = ""
    1.81 +        if mozinfo.os == "linux":
    1.82 +            pathvar = "LD_LIBRARY_PATH"
    1.83 +        elif mozinfo.os == "mac":
    1.84 +            pathvar = "DYLD_LIBRARY_PATH"
    1.85 +        elif mozinfo.os == "win":
    1.86 +            pathvar = "PATH"
    1.87 +        if pathvar:
    1.88 +            if pathvar in env:
    1.89 +                env[pathvar] = "%s%s%s" % (self.xre_path, os.pathsep, env[pathvar])
    1.90 +            else:
    1.91 +                env[pathvar] = self.xre_path
    1.92 +        return env
    1.93 +
    1.94 +class gtestOptions(OptionParser):
    1.95 +    def __init__(self):
    1.96 +        OptionParser.__init__(self)
    1.97 +        self.add_option("--xre-path",
    1.98 +                        action = "store", type = "string", dest = "xre_path",
    1.99 +                        default = None,
   1.100 +                        help = "absolute path to directory containing XRE (probably xulrunner)")
   1.101 +        self.add_option("--symbols-path",
   1.102 +                        action = "store", type = "string", dest = "symbols_path",
   1.103 +                        default = None,
   1.104 +                        help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
   1.105 +
   1.106 +def main():
   1.107 +    parser = gtestOptions()
   1.108 +    options, args = parser.parse_args()
   1.109 +    if not args:
   1.110 +        print >>sys.stderr, """Usage: %s <binary>""" % sys.argv[0]
   1.111 +        sys.exit(1)
   1.112 +    if not options.xre_path:
   1.113 +        print >>sys.stderr, """Error: --xre-path is required"""
   1.114 +        sys.exit(1)
   1.115 +    prog = os.path.abspath(args[0])
   1.116 +    options.xre_path = os.path.abspath(options.xre_path)
   1.117 +    tester = GTests()
   1.118 +    try:
   1.119 +        result = tester.run_gtest(prog, options.xre_path, options.symbols_path)
   1.120 +    except Exception, e:
   1.121 +        log.error(str(e))
   1.122 +        result = False
   1.123 +    sys.exit(0 if result else 1)
   1.124 +
   1.125 +if __name__ == '__main__':
   1.126 +    main()
   1.127 +

mercurial