Bug 1090276 - Support mach cppunittest on Android; r=dminor
authorGeoff Brown <gbrown@mozilla.com>
Mon, 14 Sep 2015 08:40:35 -0600
changeset 294929 b89b4f875debe615c069a0109311570ae7774aa6
parent 294928 ce840d7632babd00f8a2d8081ac27a06e9c99a51
child 294930 edabe4800045ffe74d5d794f427945cb9345620d
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdminor
bugs1090276
milestone43.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 1090276 - Support mach cppunittest on Android; r=dminor
testing/mach_commands.py
testing/remotecppunittests.py
testing/runcppunittests.py
--- a/testing/mach_commands.py
+++ b/testing/mach_commands.py
@@ -13,16 +13,17 @@ import shutil
 
 from mach.decorators import (
     CommandArgument,
     CommandProvider,
     Command,
 )
 
 from mozbuild.base import MachCommandBase
+from mozbuild.base import MachCommandConditions as conditions
 from argparse import ArgumentParser
 
 
 UNKNOWN_TEST = '''
 I was unable to find tests in the argument(s) given.
 
 You need to specify a test directory, filename, test suite name, or
 abbreviation.
@@ -288,40 +289,86 @@ class MachCommands(MachCommandBase):
     @CommandArgument('test_files', nargs='*', metavar='N',
         help='Test to run. Can be specified as one or more files or ' \
             'directories, or omitted. If omitted, the entire test suite is ' \
             'executed.')
 
     def run_cppunit_test(self, **params):
         import mozinfo
         from mozlog import commandline
-        import runcppunittests as cppunittests
-
         log = commandline.setup_logging("cppunittest",
                                         {},
                                         {"tbpl": sys.stdout})
 
-        if len(params['test_files']) == 0:
-            testdir = os.path.join(self.distdir, 'cppunittests')
-            manifest = os.path.join(self.topsrcdir, 'testing', 'cppunittest.ini')
-            tests = cppunittests.extract_unittests_from_args([testdir], mozinfo.info, manifest)
-        else:
-            tests = cppunittests.extract_unittests_from_args(params['test_files'], mozinfo.info, None)
-
         # See if we have crash symbols
         symbols_path = os.path.join(self.distdir, 'crashreporter-symbols')
         if not os.path.isdir(symbols_path):
             symbols_path = None
 
-        tester = cppunittests.CPPUnitTests()
+        # If no tests specified, run all tests in main manifest
+        tests = params['test_files']
+        if len(tests) == 0:
+            tests = [os.path.join(self.distdir, 'cppunittests')]
+            manifest_path = os.path.join(self.topsrcdir, 'testing', 'cppunittest.ini')
+        else:
+            manifest_path = None
+
+        if conditions.is_android(self):
+            from mozrunner.devices.android_device import verify_android_device
+            verify_android_device(self, install=False)
+            return self.run_android_test(tests, symbols_path, manifest_path, log)
+
+        return self.run_desktop_test(tests, symbols_path, manifest_path, log)
+
+    def run_desktop_test(self, tests, symbols_path, manifest_path, log):
+        import runcppunittests as cppunittests
+        from mozlog import commandline
+
+        parser = cppunittests.CPPUnittestOptions()
+        commandline.add_logging_group(parser)
+        options, args = parser.parse_args()
+
+        options.symbols_path = symbols_path
+        options.manifest_path = manifest_path
+        options.xre_path = self.bindir
+
         try:
-            result = tester.run_tests(tests, self.bindir, symbols_path, interactive=True)
+            result = cppunittests.run_test_harness(options, tests)
         except Exception as e:
             log.error("Caught exception running cpp unit tests: %s" % str(e))
             result = False
+            raise
+
+        return 0 if result else 1
+
+    def run_android_test(self, tests, symbols_path, manifest_path, log):
+        import remotecppunittests as remotecppunittests
+        from mozlog import commandline
+
+        parser = remotecppunittests.RemoteCPPUnittestOptions()
+        commandline.add_logging_group(parser)
+        options, args = parser.parse_args()
+
+        options.symbols_path = symbols_path
+        options.manifest_path = manifest_path
+        options.xre_path = self.bindir
+        options.dm_trans = "adb"
+        options.local_lib = self.bindir.replace('bin', 'fennec')
+        for file in os.listdir(os.path.join(self.topobjdir, "dist")):
+            if file.endswith(".apk") and file.startswith("fennec"):
+                options.local_apk = os.path.join(self.topobjdir, "dist", file)
+                log.info("using APK: " + options.local_apk)
+                break
+
+        try:
+            result = remotecppunittests.run_test_harness(options, tests)
+        except Exception as e:
+            log.error("Caught exception running cpp unit tests: %s" % str(e))
+            result = False
+            raise
 
         return 0 if result else 1
 
 def executable_name(name):
     return name + '.exe' if sys.platform.startswith('win') else name
 
 @CommandProvider
 class CheckSpiderMonkeyCommand(MachCommandBase):
--- a/testing/remotecppunittests.py
+++ b/testing/remotecppunittests.py
@@ -215,46 +215,32 @@ class RemoteCPPUnittestOptions(cppunitte
         self.add_option("--localBinDir", action="store",
                         type = "string", dest = "local_bin",
                         help = "local path to bin directory")
         defaults["local_bin"] = build_obj.bindir if build_obj is not None else None
 
         self.add_option("--remoteTestRoot", action = "store",
                     type = "string", dest = "remote_test_root",
                     help = "remote directory to use as test root (eg. /data/local/tests)")
+        # /data/local/tests is used because it is usually not possible to set +x permissions
+        # on binaries on /mnt/sdcard
+        defaults["remote_test_root"] = "/data/local/tests"
+
         self.add_option("--with-b2g-emulator", action = "store",
                     type = "string", dest = "with_b2g_emulator",
                     help = "Start B2G Emulator (specify path to b2g home)")
-        # /data/local/tests is used because it is usually not possible to set +x permissions
-        # on binaries on /mnt/sdcard
-        defaults["remote_test_root"] = "/data/local/tests"
 
         self.add_option("--addEnv", action = "append",
                     type = "string", dest = "add_env",
                     help = "additional remote environment variable definitions (eg. --addEnv \"somevar=something\")")
         defaults["add_env"] = None
 
         self.set_defaults(**defaults)
 
-def main():
-    parser = RemoteCPPUnittestOptions()
-    mozlog.commandline.add_logging_group(parser)
-    options, args = parser.parse_args()
-    if not args:
-        print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
-        sys.exit(1)
-    if options.local_lib is not None and not os.path.isdir(options.local_lib):
-        print >>sys.stderr, """Error: --localLib directory %s not found""" % options.local_lib
-        sys.exit(1)
-    if options.local_apk is not None and not os.path.isfile(options.local_apk):
-        print >>sys.stderr, """Error: --apk file %s not found""" % options.local_apk
-        sys.exit(1)
-    if not options.xre_path:
-        print >>sys.stderr, """Error: --xre-path is required"""
-        sys.exit(1)
+def run_test_harness(options, args):
     if options.with_b2g_emulator:
         from mozrunner import B2GEmulatorRunner
         runner = B2GEmulatorRunner(b2g_home=options.with_b2g_emulator)
         runner.start()
     if options.dm_trans == "adb":
         if options.with_b2g_emulator:
             # because we just started the emulator, we need more than the
             # default number of retries here.
@@ -272,29 +258,50 @@ def main():
                 runner.wait()
             raise
     else:
         dm = devicemanagerSUT.DeviceManagerSUT(options.device_ip, options.device_port, deviceRoot=options.remote_test_root)
         if not options.device_ip:
             print "Error: you must provide a device IP to connect to via the --deviceIP option"
             sys.exit(1)
 
-    log = mozlog.commandline.setup_logging("remotecppunittests", options,
-                                           {"tbpl": sys.stdout})
-
     options.xre_path = os.path.abspath(options.xre_path)
     cppunittests.update_mozinfo()
     progs = cppunittests.extract_unittests_from_args(args,
                                                      mozinfo.info,
                                                      options.manifest_path)
     tester = RemoteCPPUnitTests(dm, options, [item[0] for item in progs])
     try:
         result = tester.run_tests(progs, options.xre_path, options.symbols_path)
+    finally:
+        if options.with_b2g_emulator:
+            runner.cleanup()
+            runner.wait()
+    return result
+
+def main():
+    parser = RemoteCPPUnittestOptions()
+    mozlog.commandline.add_logging_group(parser)
+    options, args = parser.parse_args()
+    if not args:
+        print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
+        sys.exit(1)
+    if options.local_lib is not None and not os.path.isdir(options.local_lib):
+        print >>sys.stderr, """Error: --localLib directory %s not found""" % options.local_lib
+        sys.exit(1)
+    if options.local_apk is not None and not os.path.isfile(options.local_apk):
+        print >>sys.stderr, """Error: --apk file %s not found""" % options.local_apk
+        sys.exit(1)
+    if not options.xre_path:
+        print >>sys.stderr, """Error: --xre-path is required"""
+        sys.exit(1)
+
+    log = mozlog.commandline.setup_logging("remotecppunittests", options,
+                                           {"tbpl": sys.stdout})
+    try:
+        result = run_test_harness(options, args)
     except Exception, e:
         log.error(str(e))
         result = False
-    if options.with_b2g_emulator:
-        runner.cleanup()
-        runner.wait()
     sys.exit(0 if result else 1)
 
 if __name__ == '__main__':
     main()
--- a/testing/runcppunittests.py
+++ b/testing/runcppunittests.py
@@ -222,42 +222,44 @@ def update_mozinfo():
     dirs = set()
     while path != os.path.expanduser('~'):
         if path in dirs:
             break
         dirs.add(path)
         path = os.path.split(path)[0]
     mozinfo.find_and_update_from_json(*dirs)
 
+def run_test_harness(options, args):
+    update_mozinfo()
+    progs = extract_unittests_from_args(args, mozinfo.info, options.manifest_path)
+    options.xre_path = os.path.abspath(options.xre_path)
+    if mozinfo.isMac:
+        options.xre_path = os.path.join(os.path.dirname(options.xre_path), 'Resources')
+    tester = CPPUnitTests()
+    result = tester.run_tests(progs, options.xre_path, options.symbols_path)
+
+    return result
+
 def main():
     parser = CPPUnittestOptions()
     mozlog.commandline.add_logging_group(parser)
     options, args = parser.parse_args()
     if not args:
         print >>sys.stderr, """Usage: %s <test binary> [<test binary>...]""" % sys.argv[0]
         sys.exit(1)
     if not options.xre_path:
         print >>sys.stderr, """Error: --xre-path is required"""
         sys.exit(1)
     if options.manifest_path and len(args) > 1:
         print >>sys.stderr, "Error: multiple arguments not supported with --test-manifest"
         sys.exit(1)
-
     log = mozlog.commandline.setup_logging("cppunittests", options,
                                            {"tbpl": sys.stdout})
-
-    update_mozinfo()
-    progs = extract_unittests_from_args(args, mozinfo.info, options.manifest_path)
-    options.xre_path = os.path.abspath(options.xre_path)
-    if mozinfo.isMac:
-        options.xre_path = os.path.join(os.path.dirname(options.xre_path), 'Resources')
-    tester = CPPUnitTests()
-
     try:
-        result = tester.run_tests(progs, options.xre_path, options.symbols_path)
+        result = run_test_harness(options, args)
     except Exception as e:
         log.error(str(e))
         result = False
 
     sys.exit(0 if result else 1)
 
 if __name__ == '__main__':
     main()