|
@@ -1,403 +0,0 @@
|
|
|
-# HG changeset patch
|
|
|
-# User Geoff Brown <gbrown@mozilla.com>
|
|
|
-# Date 1521214668 21600
|
|
|
-# Node ID 0d0760485016d2fc3449a5366d364fe9e589f818
|
|
|
-# Parent 3c15d2bc6d2492729fb27e7a4a9eb396004dc8b0
|
|
|
-Bug 1440714 - Convert Android cppunit test harness to adb.py; r=bc
|
|
|
-
|
|
|
-diff --git a/testing/mozbase/mozdevice/mozdevice/__init__.py b/testing/mozbase/mozdevice/mozdevice/__init__.py
|
|
|
---- a/testing/mozbase/mozdevice/mozdevice/__init__.py
|
|
|
-+++ b/testing/mozbase/mozdevice/mozdevice/__init__.py
|
|
|
-@@ -1,17 +1,17 @@
|
|
|
- # 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/.
|
|
|
-
|
|
|
- from __future__ import absolute_import
|
|
|
-
|
|
|
--from .adb import ADBError, ADBRootError, ADBTimeoutError
|
|
|
-+from .adb import ADBError, ADBProcessError, ADBRootError, ADBTimeoutError
|
|
|
- from .adb import ADBProcess, ADBCommand, ADBHost, ADBDevice
|
|
|
- from .adb_android import ADBAndroid
|
|
|
- from .adb_b2g import ADBB2G
|
|
|
- from .devicemanager import DeviceManager, DMError
|
|
|
- from .devicemanagerADB import DeviceManagerADB
|
|
|
- from .droid import DroidADB
|
|
|
-
|
|
|
--__all__ = ['ADBError', 'ADBRootError', 'ADBTimeoutError', 'ADBProcess', 'ADBCommand', 'ADBHost',
|
|
|
-- 'ADBDevice', 'ADBAndroid', 'ADBB2G', 'DeviceManager', 'DMError',
|
|
|
-- 'DeviceManagerADB', 'DroidADB']
|
|
|
-+__all__ = ['ADBError', 'ADBProcessError', 'ADBRootError', 'ADBTimeoutError',
|
|
|
-+ 'ADBProcess', 'ADBCommand', 'ADBHost', 'ADBDevice', 'ADBAndroid', 'ADBB2G',
|
|
|
-+ 'DeviceManager', 'DMError', 'DeviceManagerADB', 'DroidADB']
|
|
|
-diff --git a/testing/mozbase/mozdevice/mozdevice/adb.py b/testing/mozbase/mozdevice/mozdevice/adb.py
|
|
|
---- a/testing/mozbase/mozdevice/mozdevice/adb.py
|
|
|
-+++ b/testing/mozbase/mozdevice/mozdevice/adb.py
|
|
|
-@@ -57,16 +57,25 @@ class ADBError(Exception):
|
|
|
- """ADBError is raised in situations where a command executed on a
|
|
|
- device either exited with a non-zero exitcode or when an
|
|
|
- unexpected error condition has occurred. Generally, ADBErrors can
|
|
|
- be handled and the device can continue to be used.
|
|
|
- """
|
|
|
- pass
|
|
|
-
|
|
|
-
|
|
|
-+class ADBProcessError(ADBError):
|
|
|
-+ """ADBProcessError is raised when an associated ADBProcess is
|
|
|
-+ available and relevant.
|
|
|
-+ """
|
|
|
-+ def __init__(self, adb_process):
|
|
|
-+ ADBError.__init__(self, str(adb_process))
|
|
|
-+ self.adb_process = adb_process
|
|
|
-+
|
|
|
-+
|
|
|
- class ADBListDevicesError(ADBError):
|
|
|
- """ADBListDevicesError is raised when errors are found listing the
|
|
|
- devices, typically not any permissions.
|
|
|
-
|
|
|
- The devices information is stocked with the *devices* member.
|
|
|
- """
|
|
|
-
|
|
|
- def __init__(self, msg, devices):
|
|
|
-@@ -275,17 +284,17 @@ class ADBCommand(object):
|
|
|
- # since ADBDevice will redefine command and call its
|
|
|
- # own version otherwise.
|
|
|
- adb_process = ADBCommand.command(self, cmds,
|
|
|
- device_serial=device_serial,
|
|
|
- timeout=timeout)
|
|
|
- if adb_process.timedout:
|
|
|
- raise ADBTimeoutError("%s" % adb_process)
|
|
|
- elif adb_process.exitcode:
|
|
|
-- raise ADBError("%s" % adb_process)
|
|
|
-+ raise ADBProcessError(adb_process)
|
|
|
- output = adb_process.stdout_file.read().rstrip()
|
|
|
- if self._verbose:
|
|
|
- self._logger.debug('command_output: %s, '
|
|
|
- 'timeout: %s, '
|
|
|
- 'timedout: %s, '
|
|
|
- 'exitcode: %s, output: %s' %
|
|
|
- (' '.join(adb_process.args),
|
|
|
- timeout,
|
|
|
-@@ -1133,17 +1142,17 @@ class ADBDevice(ADBCommand):
|
|
|
- """
|
|
|
- adb_process = None
|
|
|
- try:
|
|
|
- adb_process = self.shell(cmd, env=env, cwd=cwd,
|
|
|
- timeout=timeout, root=root)
|
|
|
- if adb_process.timedout:
|
|
|
- raise ADBTimeoutError("%s" % adb_process)
|
|
|
- elif adb_process.exitcode:
|
|
|
-- raise ADBError("%s" % adb_process)
|
|
|
-+ raise ADBProcessError(adb_process)
|
|
|
- output = adb_process.stdout_file.read().rstrip()
|
|
|
- if self._verbose:
|
|
|
- self._logger.debug('shell_output: %s, '
|
|
|
- 'timeout: %s, '
|
|
|
- 'root: %s, '
|
|
|
- 'timedout: %s, '
|
|
|
- 'exitcode: %s, '
|
|
|
- 'output: %s' %
|
|
|
-@@ -1911,17 +1920,17 @@ class ADBDevice(ADBCommand):
|
|
|
- * ADBError
|
|
|
- """
|
|
|
- adb_process = None
|
|
|
- try:
|
|
|
- adb_process = self.shell("ps", timeout=timeout)
|
|
|
- if adb_process.timedout:
|
|
|
- raise ADBTimeoutError("%s" % adb_process)
|
|
|
- elif adb_process.exitcode:
|
|
|
-- raise ADBError("%s" % adb_process)
|
|
|
-+ raise ADBProcessError(adb_process)
|
|
|
- # first line is the headers
|
|
|
- header = adb_process.stdout_file.readline()
|
|
|
- pid_i = -1
|
|
|
- user_i = -1
|
|
|
- els = header.split()
|
|
|
- for i in range(len(els)):
|
|
|
- item = els[i].lower()
|
|
|
- if item == 'user':
|
|
|
-diff --git a/testing/remotecppunittests.py b/testing/remotecppunittests.py
|
|
|
---- a/testing/remotecppunittests.py
|
|
|
-+++ b/testing/remotecppunittests.py
|
|
|
-@@ -8,55 +8,48 @@ import os
|
|
|
- import sys
|
|
|
- import subprocess
|
|
|
- from zipfile import ZipFile
|
|
|
- import runcppunittests as cppunittests
|
|
|
- import mozcrash
|
|
|
- import mozfile
|
|
|
- import mozinfo
|
|
|
- import mozlog
|
|
|
--import StringIO
|
|
|
- import posixpath
|
|
|
--from mozdevice import devicemanagerADB
|
|
|
-+from mozdevice import ADBAndroid, ADBProcessError
|
|
|
-
|
|
|
- try:
|
|
|
- from mozbuild.base import MozbuildObject
|
|
|
- build_obj = MozbuildObject.from_environment()
|
|
|
- except ImportError:
|
|
|
- build_obj = None
|
|
|
-
|
|
|
-
|
|
|
- class RemoteCPPUnitTests(cppunittests.CPPUnitTests):
|
|
|
-
|
|
|
-- def __init__(self, devmgr, options, progs):
|
|
|
-+ def __init__(self, options, progs):
|
|
|
- cppunittests.CPPUnitTests.__init__(self)
|
|
|
- self.options = options
|
|
|
-- self.device = devmgr
|
|
|
-- self.remote_test_root = self.device.deviceRoot + "/cppunittests"
|
|
|
-+ self.device = ADBAndroid(adb=options.adb_path,
|
|
|
-+ device=options.device_serial,
|
|
|
-+ test_root=options.remote_test_root)
|
|
|
-+ self.remote_test_root = posixpath.join(self.device.test_root, "cppunittests")
|
|
|
- self.remote_bin_dir = posixpath.join(self.remote_test_root, "b")
|
|
|
- self.remote_tmp_dir = posixpath.join(self.remote_test_root, "tmp")
|
|
|
- self.remote_home_dir = posixpath.join(self.remote_test_root, "h")
|
|
|
- if options.setup:
|
|
|
- self.setup_bin(progs)
|
|
|
-
|
|
|
- def setup_bin(self, progs):
|
|
|
-- if not self.device.dirExists(self.remote_test_root):
|
|
|
-- self.device.mkDir(self.remote_test_root)
|
|
|
-- if self.device.dirExists(self.remote_tmp_dir):
|
|
|
-- self.device.removeDir(self.remote_tmp_dir)
|
|
|
-- self.device.mkDir(self.remote_tmp_dir)
|
|
|
-- if self.device.dirExists(self.remote_bin_dir):
|
|
|
-- self.device.removeDir(self.remote_bin_dir)
|
|
|
-- self.device.mkDir(self.remote_bin_dir)
|
|
|
-- if self.device.dirExists(self.remote_home_dir):
|
|
|
-- self.device.removeDir(self.remote_home_dir)
|
|
|
-- self.device.mkDir(self.remote_home_dir)
|
|
|
-+ self.device.rm(self.remote_test_root, force=True, recursive=True)
|
|
|
-+ self.device.mkdir(self.remote_home_dir, parents=True)
|
|
|
-+ self.device.mkdir(self.remote_tmp_dir)
|
|
|
- self.push_libs()
|
|
|
- self.push_progs(progs)
|
|
|
-- self.device.chmodDir(self.remote_bin_dir)
|
|
|
-+ self.device.chmod(self.remote_bin_dir, recursive=True)
|
|
|
-
|
|
|
- def push_libs(self):
|
|
|
- if self.options.local_apk:
|
|
|
- with mozfile.TemporaryDirectory() as tmpdir:
|
|
|
- apk_contents = ZipFile(self.options.local_apk)
|
|
|
-
|
|
|
- for info in apk_contents.infolist():
|
|
|
- if info.filename.endswith(".so"):
|
|
|
-@@ -68,44 +61,44 @@ class RemoteCPPUnitTests(cppunittests.CP
|
|
|
- with open(local_file) as f:
|
|
|
- # Decompress xz-compressed file.
|
|
|
- if f.read(5)[1:] == '7zXZ':
|
|
|
- cmd = [
|
|
|
- 'xz', '-df', '--suffix', '.so', local_file]
|
|
|
- subprocess.check_output(cmd)
|
|
|
- # xz strips the ".so" file suffix.
|
|
|
- os.rename(local_file[:-3], local_file)
|
|
|
-- self.device.pushFile(local_file, remote_file)
|
|
|
-+ self.device.push(local_file, remote_file)
|
|
|
-
|
|
|
- elif self.options.local_lib:
|
|
|
- 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)
|
|
|
- local_file = os.path.join(self.options.local_lib, file)
|
|
|
-- self.device.pushFile(local_file, remote_file)
|
|
|
-+ self.device.push(local_file, remote_file)
|
|
|
- # Additional libraries may be found in a sub-directory such as
|
|
|
- # "lib/armeabi-v7a"
|
|
|
- for subdir in ["assets", "lib"]:
|
|
|
- local_arm_lib = os.path.join(self.options.local_lib, subdir)
|
|
|
- if os.path.isdir(local_arm_lib):
|
|
|
- for root, dirs, files in os.walk(local_arm_lib):
|
|
|
- for file in files:
|
|
|
- if (file.endswith(".so")):
|
|
|
- print >> sys.stderr, "Pushing %s.." % file
|
|
|
- remote_file = posixpath.join(
|
|
|
- self.remote_bin_dir, file)
|
|
|
- local_file = os.path.join(root, file)
|
|
|
-- self.device.pushFile(local_file, remote_file)
|
|
|
-+ self.device.push(local_file, remote_file)
|
|
|
-
|
|
|
- def push_progs(self, progs):
|
|
|
- for local_file in progs:
|
|
|
- remote_file = posixpath.join(
|
|
|
- self.remote_bin_dir, os.path.basename(local_file))
|
|
|
-- self.device.pushFile(local_file, remote_file)
|
|
|
-+ self.device.push(local_file, remote_file)
|
|
|
-
|
|
|
- def build_environment(self):
|
|
|
- env = self.build_core_environment()
|
|
|
- env['LD_LIBRARY_PATH'] = self.remote_bin_dir
|
|
|
- env["TMPDIR"] = self.remote_tmp_dir
|
|
|
- env["HOME"] = self.remote_home_dir
|
|
|
- env["MOZ_XRE_DIR"] = self.remote_bin_dir
|
|
|
- if self.options.add_env:
|
|
|
-@@ -133,26 +126,32 @@ class RemoteCPPUnitTests(cppunittests.CP
|
|
|
- symbol files for producing stack traces on crash.
|
|
|
- * timeout_factor: An optional test-specific timeout multiplier.
|
|
|
-
|
|
|
- Return True if the program exits with a zero status, False otherwise.
|
|
|
- """
|
|
|
- basename = os.path.basename(prog)
|
|
|
- remote_bin = posixpath.join(self.remote_bin_dir, basename)
|
|
|
- self.log.test_start(basename)
|
|
|
-- buf = StringIO.StringIO()
|
|
|
- test_timeout = cppunittests.CPPUnitTests.TEST_PROC_TIMEOUT * \
|
|
|
- timeout_factor
|
|
|
-- returncode = self.device.shell(
|
|
|
-- [remote_bin], buf, env=env, cwd=self.remote_home_dir,
|
|
|
-- timeout=test_timeout)
|
|
|
-- self.log.process_output(basename, "\n%s" % buf.getvalue(),
|
|
|
-+
|
|
|
-+ try:
|
|
|
-+ output = self.device.shell_output(remote_bin, env=env,
|
|
|
-+ cwd=self.remote_home_dir,
|
|
|
-+ timeout=test_timeout)
|
|
|
-+ returncode = 0
|
|
|
-+ except ADBProcessError as e:
|
|
|
-+ output = e.adb_process.stdout
|
|
|
-+ returncode = e.adb_process.exitcode
|
|
|
-+
|
|
|
-+ self.log.process_output(basename, "\n%s" % output,
|
|
|
- command=[remote_bin])
|
|
|
- with mozfile.TemporaryDirectory() as tempdir:
|
|
|
-- self.device.getDirectory(self.remote_home_dir, tempdir)
|
|
|
-+ self.device.pull(self.remote_home_dir, tempdir)
|
|
|
- if mozcrash.check_for_crashes(tempdir, symbols_path,
|
|
|
- test_name=basename):
|
|
|
- self.log.test_end(basename, status='CRASH', expected='PASS')
|
|
|
- return False
|
|
|
- result = returncode == 0
|
|
|
- if not result:
|
|
|
- self.log.test_end(basename, status='FAIL', expected='PASS',
|
|
|
- message=("test failed with return code %s" %
|
|
|
-@@ -163,25 +162,20 @@ class RemoteCPPUnitTests(cppunittests.CP
|
|
|
-
|
|
|
-
|
|
|
- class RemoteCPPUnittestOptions(cppunittests.CPPUnittestOptions):
|
|
|
-
|
|
|
- def __init__(self):
|
|
|
- cppunittests.CPPUnittestOptions.__init__(self)
|
|
|
- defaults = {}
|
|
|
-
|
|
|
-- self.add_option("--deviceIP", action="store",
|
|
|
-- type="string", dest="device_ip",
|
|
|
-- help="ip address of remote device to test")
|
|
|
-- defaults["device_ip"] = None
|
|
|
--
|
|
|
-- self.add_option("--devicePort", action="store",
|
|
|
-- type="string", dest="device_port",
|
|
|
-- help="port of remote device to test")
|
|
|
-- defaults["device_port"] = 20701
|
|
|
-+ self.add_option("--deviceSerial", action="store",
|
|
|
-+ type="string", dest="device_serial",
|
|
|
-+ help="serial ID of device")
|
|
|
-+ defaults["device_serial"] = None
|
|
|
-
|
|
|
- self.add_option("--noSetup", action="store_false",
|
|
|
- dest="setup",
|
|
|
- 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",
|
|
|
-@@ -202,69 +196,33 @@ class RemoteCPPUnittestOptions(cppunitte
|
|
|
-
|
|
|
- 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)")
|
|
|
-- self.add_option("--emulator", default="arm", choices=["x86", "arm"],
|
|
|
-- help="Architecture of emulator to use: x86 or arm")
|
|
|
- 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 run_test_harness(options, args):
|
|
|
-- if options.with_b2g_emulator:
|
|
|
-- from mozrunner import B2GEmulatorRunner
|
|
|
-- runner = B2GEmulatorRunner(
|
|
|
-- arch=options.emulator, b2g_home=options.with_b2g_emulator)
|
|
|
-- runner.start()
|
|
|
-- # because we just started the emulator, we need more than the
|
|
|
-- # default number of retries here.
|
|
|
-- retryLimit = 50
|
|
|
-- else:
|
|
|
-- retryLimit = 5
|
|
|
-- try:
|
|
|
-- dm_args = {'deviceRoot': options.remote_test_root}
|
|
|
-- dm_args['retryLimit'] = retryLimit
|
|
|
-- if options.device_ip:
|
|
|
-- dm_args['host'] = options.device_ip
|
|
|
-- dm_args['port'] = options.device_port
|
|
|
-- if options.log_tbpl_level == 'debug' or options.log_mach_level == 'debug':
|
|
|
-- dm_args['logLevel'] = logging.DEBUG # noqa python 2 / 3
|
|
|
-- dm = devicemanagerADB.DeviceManagerADB(**dm_args)
|
|
|
-- except BaseException:
|
|
|
-- if options.with_b2g_emulator:
|
|
|
-- runner.cleanup()
|
|
|
-- runner.wait()
|
|
|
-- raise
|
|
|
--
|
|
|
- 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()
|
|
|
-+ tester = RemoteCPPUnitTests(options, [item[0] for item in progs])
|
|
|
-+ result = tester.run_tests(progs, options.xre_path, options.symbols_path)
|
|
|
- return result
|
|
|
-
|
|
|
-
|
|
|
- def main():
|
|
|
- parser = RemoteCPPUnittestOptions()
|
|
|
- mozlog.commandline.add_logging_group(parser)
|
|
|
- options, args = parser.parse_args()
|
|
|
- if not args:
|
|
|
-diff --git a/testing/remotecppunittests.py.1440714-07.later b/testing/remotecppunittests.py.1440714-07.later
|
|
|
-new file mode 100644
|
|
|
---- /dev/null
|
|
|
-+++ b/testing/remotecppunittests.py.1440714-07.later
|
|
|
-@@ -0,0 +1,21 @@
|
|
|
-+--- remotecppunittests.py
|
|
|
-++++ remotecppunittests.py
|
|
|
-+@@ -163,17 +163,17 @@ class RemoteCPPUnitTests(cppunittests.CP
|
|
|
-+ self.add_option("--deviceSerial", action="store",
|
|
|
-+ type="string", dest="device_serial",
|
|
|
-+ help="serial ID of device")
|
|
|
-+ defaults["device_serial"] = None
|
|
|
-+
|
|
|
-+ self.add_option("--adbPath", action="store",
|
|
|
-+ type="string", dest="adb_path",
|
|
|
-+ help="Path to adb")
|
|
|
-+- defaults["adb_path"] = None
|
|
|
-++ defaults["adb_path"] = "adb"
|
|
|
-+
|
|
|
-+ self.add_option("--noSetup", action="store_false",
|
|
|
-+ dest="setup",
|
|
|
-+ 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",
|