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 141165 d6d7900215918382ff6e0d59605142e93ebf148d
parent 141164 58aed54902a539f23033a205382c05e582311661
child 141166 471dcc138dfee3eecf7e4ef9c0d4e78f9bb20218
push id2018
push userryanvm@gmail.com
push dateFri, 02 Aug 2013 21:12:22 +0000
treeherderfx-team@d0edf8086809 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersted
bugs893085
milestone25.0a1
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)