Bug 844292 - Add a mach target for GTest. r=gps DONTBUILD as NPOTB
authorBenoit Girard <b56girard@gmail.com>
Wed, 27 Mar 2013 19:15:18 -0400
changeset 126579 30bea74a353eb0c9d3cd73811eec051254a9b578
parent 126578 c69d74aecb032cdcc87d82f442a1c3189650ce2f
child 126580 ba144296a12883b03880c2a25d2aa95b0b432c22
push id24488
push userryanvm@gmail.com
push dateFri, 29 Mar 2013 00:54:52 +0000
treeherdermozilla-central@8aeabe064932 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgps
bugs844292
milestone22.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 844292 - Add a mach target for GTest. r=gps DONTBUILD as NPOTB
python/mozbuild/mozbuild/mach_commands.py
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -269,16 +269,78 @@ class Warnings(MachCommandBase):
             if warning['column'] is not None:
                 print('%s:%d:%d [%s] %s' % (filename, warning['line'],
                     warning['column'], warning['flag'], warning['message']))
             else:
                 print('%s:%d [%s] %s' % (filename, warning['line'],
                     warning['flag'], warning['message']))
 
 @CommandProvider
+class GTestCommands(MachCommandBase):
+    @Command('gtest', help='Run GTest unit tests.')
+    @CommandArgument('gtest_filter', default='*', nargs='?', metavar='gtest_filter',
+        help="test_filter is a ':'-separated list of wildcard patterns (called the positive patterns),"
+             "optionally followed by a '-' and another ':'-separated pattern list (called the negative patterns).")
+    @CommandArgument('--jobs', '-j', default='1', nargs='?', metavar='jobs', type=int,
+        help='Run the tests in parallel using multiple processes.')
+    @CommandArgument('--tbpl-parser', '-t', action='store_true',
+        help='Output test results in a format that can be parsed by TBPL.')
+    @CommandArgument('--shuffle', '-s', action='store_true',
+        help='Randomize the execution order of tests.')
+    def gtest(self, shuffle, jobs, gtest_filter, tbpl_parser):
+        app_path = self.get_binary_path('app')
+
+        # Use GTest environment variable to control test execution
+        # For details see:
+        # https://code.google.com/p/googletest/wiki/AdvancedGuide#Running_Test_Programs:_Advanced_Options
+        gtest_env = {b'GTEST_FILTER': gtest_filter}
+
+        if shuffle:
+            gtest_env[b"GTEST_SHUFFLE"] = b"True"
+
+        if tbpl_parser:
+            gtest_env[b"MOZ_TBPL_PARSER"] = b"True"
+
+        if jobs == 1:
+            return self.run_process([app_path, "-unittest"],
+                                    append_env=gtest_env,
+                                    ensure_exit_code=False,
+                                    pass_thru=True)
+
+        from mozprocess import ProcessHandlerMixin
+        import functools
+        def handle_line(job_id, line):
+            # Prepend the jobId
+            line = '[%d] %s' % (job_id + 1, line.strip())
+            self.log(logging.INFO, "GTest", {'line': line}, '{line}')
+
+        gtest_env["GTEST_TOTAL_SHARDS"] = str(jobs)
+        processes = {}
+        for i in range(0, jobs):
+            gtest_env["GTEST_SHARD_INDEX"] = str(i)
+            processes[i] = ProcessHandlerMixin([app_path, "-unittest"],
+                             env=gtest_env,
+                             processOutputLine=[functools.partial(handle_line, i)],
+                             universal_newlines=True)
+            processes[i].run()
+
+        exit_code = 0
+        for process in processes.values():
+            status = process.wait()
+            if status:
+                exit_code = status
+
+        # Clamp error code to 255 to prevent overflowing multiple of
+        # 256 into 0
+        if exit_code > 255:
+            exit_code = 255
+
+        return exit_code
+
+@CommandProvider
 class ClangCommands(MachCommandBase):
     @Command('clang-complete', help='Generate a .clang_complete file.')
     def clang_complete(self):
         import shlex
 
         build_vars = {}
 
         def on_line(line):