Bug 893085 - remotecppunittests.py should accept --apk option and test directories as well as files on the command line; r=ted
authorDan Minor <dminor@mozilla.com>
Fri, 02 Aug 2013 09:53:13 -0400
changeset 141141 d6d7900215918382ff6e0d59605142e93ebf148d
parent 141140 58aed54902a539f23033a205382c05e582311661
child 141142 471dcc138dfee3eecf7e4ef9c0d4e78f9bb20218
push id25048
push userryanvm@gmail.com
push dateFri, 02 Aug 2013 20:52:37 +0000
treeherdermozilla-central@d2ce76654a6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs893085
milestone25.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 893085 - remotecppunittests.py should accept --apk option and test directories as well as files on the command line; r=ted
testing/remotecppunittests.py
testing/runcppunittests.py
--- a/testing/remotecppunittests.py
+++ b/testing/remotecppunittests.py
@@ -1,21 +1,31 @@
 #!/usr/bin/env python
 #
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import os, sys
+import subprocess
+import tempfile
+from zipfile import ZipFile
 import runcppunittests as cppunittests
 import mozcrash, mozlog
+import mozfile
 import StringIO
 import posixpath
 from mozdevice import devicemanager, devicemanagerADB, devicemanagerSUT
 
+try:
+    from mozbuild.base import MozbuildObject
+    build_obj = MozbuildObject.from_environment()
+except ImportError:
+    build_obj = None
+
 log = mozlog.getLogger('remotecppunittests')
 
 class RemoteCPPUnitTests(cppunittests.CPPUnitTests):
     def __init__(self, devmgr, options, progs):
         cppunittests.CPPUnitTests.__init__(self)
         self.options = options
         self.device = devmgr
         self.remote_test_root = self.device.getDeviceRoot() + "/cppunittests"
@@ -37,16 +47,39 @@ class RemoteCPPUnitTests(cppunittests.CP
         if self.device.dirExists(self.remote_home_dir):
             self.device.removeDir(self.remote_home_dir)
         self.device.mkDir(self.remote_home_dir)
         self.push_libs()
         self.push_progs(progs)
         self.device.chmodDir(self.remote_bin_dir)
 
     def push_libs(self):
+        if self.options.local_apk:
+            with mozfile.TemporaryDirectory() as tmpdir:
+                apk_contents = ZipFile(self.options.local_apk)
+                szip = os.path.join(self.options.local_bin, '..', 'host', 'bin', 'szip')
+                if not os.path.exists(szip):
+                    # Tinderbox builds must run szip from the test package
+                    szip = os.path.join(self.options.local_bin, 'host', 'szip')
+                if not os.path.exists(szip):
+                    # If the test package doesn't contain szip, it means files
+                    # are not szipped in the test package.
+                    szip = None
+
+                for info in apk_contents.infolist():
+                    if info.filename.endswith(".so"):
+                        print >> sys.stderr, "Pushing %s.." % info.filename
+                        remote_file = posixpath.join(self.remote_bin_dir, os.path.basename(info.filename))
+                        apk_contents.extract(info, tmpdir)
+                        file = os.path.join(tmpdir, info.filename)
+                        if szip:
+                            out = subprocess.check_output([szip, '-d', file], stderr=subprocess.STDOUT)
+                        self.device.pushFile(os.path.join(tmpdir, info.filename), remote_file)
+            return
+
         for file in os.listdir(self.options.local_lib):
             if file.endswith(".so"):
                 print >> sys.stderr, "Pushing %s.." % file
                 remote_file = posixpath.join(self.remote_bin_dir, file)
                 self.device.pushFile(os.path.join(self.options.local_lib, file), remote_file)
         # Additional libraries may be found in a sub-directory such as "lib/armeabi-v7a"
         local_arm_lib = os.path.join(self.options.local_lib, "lib")
         if os.path.isdir(local_arm_lib):
@@ -136,16 +169,26 @@ class RemoteCPPUnittestOptions(cppunitte
                         help = "do not copy any files to device (to be used only if device is already setup)")
         defaults["setup"] = True
 
         self.add_option("--localLib", action="store",
                         type = "string", dest = "local_lib",
                         help = "location of libraries to push -- preferably stripped")
         defaults["local_lib"] = None
 
+        self.add_option("--apk", action="store",
+                        type = "string", dest = "local_apk",
+                        help = "local path to Fennec APK")
+        defaults["local_apk"] = None
+
+        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("--addEnv", action = "append",
@@ -156,37 +199,40 @@ class RemoteCPPUnittestOptions(cppunitte
         self.set_defaults(**defaults)
 
 def main():
     parser = RemoteCPPUnittestOptions()
     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.local_lib:
-        print >>sys.stderr, """Error: --localLib is required"""
+    if options.local_lib is None and options.local_apk is None:
+        print >>sys.stderr, """Error: --localLib or --apk is required"""
         sys.exit(1)
-    if not os.path.isdir(options.local_lib):
+    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)
     if options.dm_trans == "adb":
         if options.device_ip:
             dm = devicemanagerADB.DeviceManagerADB(options.device_ip, options.device_port, packageName=None, deviceRoot=options.remote_test_root)
         else:
             dm = devicemanagerADB.DeviceManagerADB(packageName=None, deviceRoot=options.remote_test_root)
     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)
     options.xre_path = os.path.abspath(options.xre_path)
-    progs = [os.path.abspath(p) for p in args]
+    progs = cppunittests.extract_unittests_from_args(args)
     tester = RemoteCPPUnitTests(dm, options, progs)
     try:
         result = tester.run_tests(progs, options.xre_path, options.symbols_path)
     except Exception, e:
         log.error(str(e))
         result = False
     sys.exit(0 if result else 1)
 
--- a/testing/runcppunittests.py
+++ b/testing/runcppunittests.py
@@ -125,32 +125,39 @@ class CPPUnittestOptions(OptionParser):
                         action = "store", type = "string", dest = "xre_path",
                         default = None,
                         help = "absolute path to directory containing XRE (probably xulrunner)")
         self.add_option("--symbols-path",
                         action = "store", type = "string", dest = "symbols_path",
                         default = None,
                         help = "absolute path to directory containing breakpad symbols, or the URL of a zip file containing symbols")
 
+def extract_unittests_from_args(args):
+    """Extract unittests from args, expanding directories as needed"""
+    progs = []
+
+    for p in args:
+        if os.path.isdir(p):
+            #filter out .py files packaged with the unit tests
+            progs.extend([os.path.abspath(os.path.join(p, x)) for x in os.listdir(p) if not x.endswith('.py')])
+        else:
+            progs.append(os.path.abspath(p))
+
+    return progs
+
 def main():
     parser = CPPUnittestOptions()
     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)
-    progs = []
-    for p in args:
-        if os.path.isdir(p):
-            #filter out .py files packaged with the unit tests
-            progs.extend([os.path.abspath(os.path.join(p, x)) for x in os.listdir(p) if not x.endswith('.py')])
-        else:
-            progs.append(os.path.abspath(p))
+    progs = extract_unittests_from_args(args)
     options.xre_path = os.path.abspath(options.xre_path)
     tester = CPPUnitTests()
     try:
         result = tester.run_tests(progs, options.xre_path, options.symbols_path)
     except Exception, e:
         log.error(str(e))
         result = False
     sys.exit(0 if result else 1)