mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 811388 - Update mozdevice to 0.15, update consumers;r=ahal
This commit is contained in:
parent
807a0d0fb3
commit
5a3130a3ae
@ -294,9 +294,9 @@ class B2GRemoteAutomation(Automation):
|
|||||||
# into a queue. The lines in this queue are
|
# into a queue. The lines in this queue are
|
||||||
# retrieved and returned by accessing the stdout property of
|
# retrieved and returned by accessing the stdout property of
|
||||||
# this class.
|
# this class.
|
||||||
cmd = [self.dm.adbPath]
|
cmd = [self.dm._adbPath]
|
||||||
if self.dm.deviceSerial:
|
if self.dm._deviceSerial:
|
||||||
cmd.extend(['-s', self.dm.deviceSerial])
|
cmd.extend(['-s', self.dm._deviceSerial])
|
||||||
cmd.append('shell')
|
cmd.append('shell')
|
||||||
cmd.append('/system/bin/b2g.sh')
|
cmd.append('/system/bin/b2g.sh')
|
||||||
proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
|
proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
|
||||||
|
@ -253,7 +253,7 @@ class B2GReftest(RefTest):
|
|||||||
|
|
||||||
# Restore the original user.js.
|
# Restore the original user.js.
|
||||||
self._devicemanager._checkCmdAs(['shell', 'rm', '-f', self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'rm', '-f', self.userJS])
|
||||||
if self._devicemanager.useDDCopy:
|
if self._devicemanager._useDDCopy:
|
||||||
self._devicemanager._checkCmdAs(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
|
||||||
else:
|
else:
|
||||||
self._devicemanager._checkCmdAs(['shell', 'cp', '%s.orig' % self.userJS, self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'cp', '%s.orig' % self.userJS, self.userJS])
|
||||||
@ -435,7 +435,7 @@ user_pref("capability.principal.codebase.p2.id", "http://%s:%s");
|
|||||||
# In B2G, user.js is always read from /data/local, not the profile
|
# In B2G, user.js is always read from /data/local, not the profile
|
||||||
# directory. Backup the original user.js first so we can restore it.
|
# directory. Backup the original user.js first so we can restore it.
|
||||||
self._devicemanager._checkCmdAs(['shell', 'rm', '-f', '%s.orig' % self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'rm', '-f', '%s.orig' % self.userJS])
|
||||||
if self._devicemanager.useDDCopy:
|
if self._devicemanager._useDDCopy:
|
||||||
self._devicemanager._checkCmdAs(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
|
||||||
else:
|
else:
|
||||||
self._devicemanager._checkCmdAs(['shell', 'cp', self.userJS, '%s.orig' % self.userJS])
|
self._devicemanager._checkCmdAs(['shell', 'cp', self.userJS, '%s.orig' % self.userJS])
|
||||||
|
@ -212,7 +212,7 @@ class B2GMochitest(Mochitest):
|
|||||||
self.originalProfilesIni = None
|
self.originalProfilesIni = None
|
||||||
|
|
||||||
def copyRemoteFile(self, src, dest):
|
def copyRemoteFile(self, src, dest):
|
||||||
if self._dm.useDDCopy:
|
if self._dm._useDDCopy:
|
||||||
self._dm._checkCmdAs(['shell', 'dd', 'if=%s' % src,'of=%s' % dest])
|
self._dm._checkCmdAs(['shell', 'dd', 'if=%s' % src,'of=%s' % dest])
|
||||||
else:
|
else:
|
||||||
self._dm._checkCmdAs(['shell', 'cp', src, dest])
|
self._dm._checkCmdAs(['shell', 'cp', src, dest])
|
||||||
|
@ -33,7 +33,7 @@ def abstractmethod(method):
|
|||||||
|
|
||||||
class DeviceManager:
|
class DeviceManager:
|
||||||
|
|
||||||
logcatNeedsRoot = True
|
_logcatNeedsRoot = True
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False):
|
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False):
|
||||||
@ -362,13 +362,15 @@ class DeviceManager:
|
|||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def getIP(self, conn_type='eth0'):
|
def getIP(self, interfaces=['eth0', 'wlan0']):
|
||||||
"""
|
"""
|
||||||
Gets the IP of the device, or None if no connection exists.
|
Gets the IP of the device, or None if no connection exists.
|
||||||
"""
|
"""
|
||||||
match = re.match(r"%s: ip (\S+)" % conn_type, self.shellCheckOutput(['ifconfig', conn_type]))
|
for interface in interfaces:
|
||||||
if match:
|
match = re.match(r"%s: ip (\S+)" % interface,
|
||||||
return match.group(1)
|
self.shellCheckOutput(['ifconfig', interface]))
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def unpackFile(self, file_path, dest_dir=None):
|
def unpackFile(self, file_path, dest_dir=None):
|
||||||
@ -489,7 +491,7 @@ class DeviceManager:
|
|||||||
#TODO: spawn this off in a separate thread/process so we can collect all the logcat information
|
#TODO: spawn this off in a separate thread/process so we can collect all the logcat information
|
||||||
|
|
||||||
# Right now this is just clearing the logcat so we can only see what happens after this call.
|
# Right now this is just clearing the logcat so we can only see what happens after this call.
|
||||||
self.shellCheckOutput(['/system/bin/logcat', '-c'], root=self.logcatNeedsRoot)
|
self.shellCheckOutput(['/system/bin/logcat', '-c'], root=self._logcatNeedsRoot)
|
||||||
|
|
||||||
def getLogcat(self, filterSpecs=["dalvikvm:S", "ConnectivityService:S",
|
def getLogcat(self, filterSpecs=["dalvikvm:S", "ConnectivityService:S",
|
||||||
"WifiMonitor:S", "WifiStateTracker:S",
|
"WifiMonitor:S", "WifiStateTracker:S",
|
||||||
@ -501,7 +503,7 @@ class DeviceManager:
|
|||||||
"""
|
"""
|
||||||
cmdline = ["/system/bin/logcat", "-v", format, "-d"] + filterSpecs
|
cmdline = ["/system/bin/logcat", "-v", format, "-d"] + filterSpecs
|
||||||
lines = self.shellCheckOutput(cmdline,
|
lines = self.shellCheckOutput(cmdline,
|
||||||
root=self.logcatNeedsRoot).split('\r')
|
root=self._logcatNeedsRoot).split('\r')
|
||||||
|
|
||||||
for regex in filterOutRegexps:
|
for regex in filterOutRegexps:
|
||||||
lines = [line for line in lines if not re.search(regex, line)]
|
lines = [line for line in lines if not re.search(regex, line)]
|
||||||
|
@ -6,44 +6,44 @@ import subprocess
|
|||||||
from devicemanager import DeviceManager, DMError, _pop_last_line
|
from devicemanager import DeviceManager, DMError, _pop_last_line
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
class DeviceManagerADB(DeviceManager):
|
class DeviceManagerADB(DeviceManager):
|
||||||
|
|
||||||
|
_haveRootShell = False
|
||||||
|
_haveSu = False
|
||||||
|
_useRunAs = False
|
||||||
|
_useDDCopy = False
|
||||||
|
_useZip = False
|
||||||
|
_logcatNeedsRoot = False
|
||||||
|
_pollingInterval = 0.01
|
||||||
|
_packageName = None
|
||||||
|
_tempDir = None
|
||||||
|
default_timeout = 300
|
||||||
|
|
||||||
def __init__(self, host=None, port=20701, retrylimit=5, packageName='fennec',
|
def __init__(self, host=None, port=20701, retrylimit=5, packageName='fennec',
|
||||||
adbPath='adb', deviceSerial=None, deviceRoot=None, **kwargs):
|
adbPath='adb', deviceSerial=None, deviceRoot=None, **kwargs):
|
||||||
self.host = host
|
self.host = host
|
||||||
self.port = port
|
self.port = port
|
||||||
self.retrylimit = retrylimit
|
self.retrylimit = retrylimit
|
||||||
self.retries = 0
|
|
||||||
self._sock = None
|
|
||||||
self.haveRootShell = False
|
|
||||||
self.haveSu = False
|
|
||||||
self.useRunAs = False
|
|
||||||
self.useDDCopy = False
|
|
||||||
self.useZip = False
|
|
||||||
self.logcatNeedsRoot = False
|
|
||||||
self.packageName = None
|
|
||||||
self.tempDir = None
|
|
||||||
self.deviceRoot = deviceRoot
|
self.deviceRoot = deviceRoot
|
||||||
self.default_timeout = 300
|
|
||||||
self.pollingInterval = 0.01
|
|
||||||
|
|
||||||
# the path to adb, or 'adb' to assume that it's on the PATH
|
# the path to adb, or 'adb' to assume that it's on the PATH
|
||||||
self.adbPath = adbPath
|
self._adbPath = adbPath
|
||||||
|
|
||||||
# The serial number of the device to use with adb, used in cases
|
# The serial number of the device to use with adb, used in cases
|
||||||
# where multiple devices are being managed by the same adb instance.
|
# where multiple devices are being managed by the same adb instance.
|
||||||
self.deviceSerial = deviceSerial
|
self._deviceSerial = deviceSerial
|
||||||
|
|
||||||
if packageName == 'fennec':
|
if packageName == 'fennec':
|
||||||
if os.getenv('USER'):
|
if os.getenv('USER'):
|
||||||
self.packageName = 'org.mozilla.fennec_' + os.getenv('USER')
|
self._packageName = 'org.mozilla.fennec_' + os.getenv('USER')
|
||||||
else:
|
else:
|
||||||
self.packageName = 'org.mozilla.fennec_'
|
self._packageName = 'org.mozilla.fennec_'
|
||||||
elif packageName:
|
elif packageName:
|
||||||
self.packageName = packageName
|
self._packageName = packageName
|
||||||
|
|
||||||
# verify that we can run the adb command. can't continue otherwise
|
# verify that we can run the adb command. can't continue otherwise
|
||||||
self._verifyADB()
|
self._verifyADB()
|
||||||
@ -96,7 +96,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
# always. :(
|
# always. :(
|
||||||
|
|
||||||
# If requested to run as root, check that we can actually do that
|
# If requested to run as root, check that we can actually do that
|
||||||
if root and not self.haveRootShell and not self.haveSu:
|
if root and not self._haveRootShell and not self._haveSu:
|
||||||
raise DMError("Shell command '%s' requested to run as root but root "
|
raise DMError("Shell command '%s' requested to run as root but root "
|
||||||
"is not available on this device. Root your device or "
|
"is not available on this device. Root your device or "
|
||||||
"refactor the test/harness to not require root." %
|
"refactor the test/harness to not require root." %
|
||||||
@ -105,7 +105,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
# Getting the return code is more complex than you'd think because adb
|
# Getting the return code is more complex than you'd think because adb
|
||||||
# doesn't actually return the return code from a process, so we have to
|
# doesn't actually return the return code from a process, so we have to
|
||||||
# capture the output to get it
|
# capture the output to get it
|
||||||
if root and not self.haveRootShell:
|
if root and not self._haveRootShell:
|
||||||
cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd)
|
cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd)
|
||||||
else:
|
else:
|
||||||
cmdline = self._escapedCommandLine(cmd)
|
cmdline = self._escapedCommandLine(cmd)
|
||||||
@ -119,9 +119,9 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
cmdline = envstr + "; " + cmdline
|
cmdline = envstr + "; " + cmdline
|
||||||
|
|
||||||
# all output should be in stdout
|
# all output should be in stdout
|
||||||
args=[self.adbPath]
|
args=[self._adbPath]
|
||||||
if self.deviceSerial:
|
if self._deviceSerial:
|
||||||
args.extend(['-s', self.deviceSerial])
|
args.extend(['-s', self._deviceSerial])
|
||||||
args.extend(["shell", cmdline])
|
args.extend(["shell", cmdline])
|
||||||
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||||
|
|
||||||
@ -133,7 +133,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
ret_code = proc.poll()
|
ret_code = proc.poll()
|
||||||
while ((time.time() - start_time) <= timeout) and ret_code == None:
|
while ((time.time() - start_time) <= timeout) and ret_code == None:
|
||||||
time.sleep(self.pollingInterval)
|
time.sleep(self._pollingInterval)
|
||||||
ret_code = proc.poll()
|
ret_code = proc.poll()
|
||||||
if ret_code == None:
|
if ret_code == None:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
@ -170,10 +170,10 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
raise DMError("Attempted to push a file (%s) to a directory (%s)!" %
|
raise DMError("Attempted to push a file (%s) to a directory (%s)!" %
|
||||||
(localname, destname))
|
(localname, destname))
|
||||||
|
|
||||||
if self.useRunAs:
|
if self._useRunAs:
|
||||||
remoteTmpFile = self.getTempDir() + "/" + os.path.basename(localname)
|
remoteTmpFile = self.getTempDir() + "/" + os.path.basename(localname)
|
||||||
self._checkCmd(["push", os.path.realpath(localname), remoteTmpFile])
|
self._checkCmd(["push", os.path.realpath(localname), remoteTmpFile])
|
||||||
if self.useDDCopy:
|
if self._useDDCopy:
|
||||||
self.shellCheckOutput(["dd", "if=" + remoteTmpFile, "of=" + destname])
|
self.shellCheckOutput(["dd", "if=" + remoteTmpFile, "of=" + destname])
|
||||||
else:
|
else:
|
||||||
self.shellCheckOutput(["cp", remoteTmpFile, destname])
|
self.shellCheckOutput(["cp", remoteTmpFile, destname])
|
||||||
@ -195,11 +195,11 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
"""
|
"""
|
||||||
# adb "push" accepts a directory as an argument, but if the directory
|
# adb "push" accepts a directory as an argument, but if the directory
|
||||||
# contains symbolic links, the links are pushed, rather than the linked
|
# contains symbolic links, the links are pushed, rather than the linked
|
||||||
# files; we either zip/unzip or push file-by-file to get around this
|
# files; we either zip/unzip or re-copy the directory into a temporary
|
||||||
# limitation
|
# one to get around this limitation
|
||||||
if not self.dirExists(remoteDir):
|
if not self.dirExists(remoteDir):
|
||||||
self.mkDirs(remoteDir+"/x")
|
self.mkDirs(remoteDir+"/x")
|
||||||
if self.useZip:
|
if self._useZip:
|
||||||
try:
|
try:
|
||||||
localZip = tempfile.mktemp() + ".zip"
|
localZip = tempfile.mktemp() + ".zip"
|
||||||
remoteZip = remoteDir + "/adbdmtmp.zip"
|
remoteZip = remoteDir + "/adbdmtmp.zip"
|
||||||
@ -212,24 +212,15 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
raise Exception("unzip failed, or permissions error")
|
raise Exception("unzip failed, or permissions error")
|
||||||
except:
|
except:
|
||||||
print "zip/unzip failure: falling back to normal push"
|
print "zip/unzip failure: falling back to normal push"
|
||||||
self.useZip = False
|
self._useZip = False
|
||||||
self.pushDir(localDir, remoteDir)
|
self.pushDir(localDir, remoteDir)
|
||||||
else:
|
else:
|
||||||
for root, dirs, files in os.walk(localDir, followlinks=True):
|
tmpDir = tempfile.mkdtemp()
|
||||||
relRoot = os.path.relpath(root, localDir)
|
# copytree's target dir must not already exist, so create a subdir
|
||||||
for f in files:
|
tmpDirTarget = os.path.join(tmpDir, "tmp")
|
||||||
localFile = os.path.join(root, f)
|
shutil.copytree(localDir, tmpDirTarget)
|
||||||
remoteFile = remoteDir + "/"
|
self._checkCmd(["push", tmpDirTarget, remoteDir])
|
||||||
if relRoot != ".":
|
shutil.rmtree(tmpDir)
|
||||||
remoteFile = remoteFile + relRoot + "/"
|
|
||||||
remoteFile = remoteFile + f
|
|
||||||
self.pushFile(localFile, remoteFile)
|
|
||||||
for d in dirs:
|
|
||||||
targetDir = remoteDir + "/"
|
|
||||||
if relRoot != ".":
|
|
||||||
targetDir = targetDir + relRoot + "/"
|
|
||||||
targetDir = targetDir + d
|
|
||||||
self.mkDir(targetDir)
|
|
||||||
|
|
||||||
def dirExists(self, remotePath):
|
def dirExists(self, remotePath):
|
||||||
"""
|
"""
|
||||||
@ -418,7 +409,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
if (len(errl) == 1):
|
if (len(errl) == 1):
|
||||||
if (((errl[0].find("Permission denied") != -1)
|
if (((errl[0].find("Permission denied") != -1)
|
||||||
or (errl[0].find("does not exist") != -1))
|
or (errl[0].find("does not exist") != -1))
|
||||||
and self.useRunAs):
|
and self._useRunAs):
|
||||||
# If we lack permissions to read but have run-as, then we should try
|
# If we lack permissions to read but have run-as, then we should try
|
||||||
# to copy the file to a world-readable location first before attempting
|
# to copy the file to a world-readable location first before attempting
|
||||||
# to pull it again.
|
# to pull it again.
|
||||||
@ -544,11 +535,11 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
"""
|
"""
|
||||||
# Cache result to speed up operations depending
|
# Cache result to speed up operations depending
|
||||||
# on the temporary directory.
|
# on the temporary directory.
|
||||||
if not self.tempDir:
|
if not self._tempDir:
|
||||||
self.tempDir = self.getDeviceRoot() + "/tmp"
|
self._tempDir = self.getDeviceRoot() + "/tmp"
|
||||||
self.mkDir(self.tempDir)
|
self.mkDir(self._tempDir)
|
||||||
|
|
||||||
return self.tempDir
|
return self._tempDir
|
||||||
|
|
||||||
def getAppRoot(self, packageName):
|
def getAppRoot(self, packageName):
|
||||||
"""
|
"""
|
||||||
@ -561,10 +552,10 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
if (packageName and self.dirExists('/data/data/' + packageName)):
|
if (packageName and self.dirExists('/data/data/' + packageName)):
|
||||||
self.packageName = packageName
|
self._packageName = packageName
|
||||||
return '/data/data/' + packageName
|
return '/data/data/' + packageName
|
||||||
elif (self.packageName and self.dirExists('/data/data/' + self.packageName)):
|
elif (self._packageName and self.dirExists('/data/data/' + self._packageName)):
|
||||||
return '/data/data/' + self.packageName
|
return '/data/data/' + self._packageName
|
||||||
|
|
||||||
# Failure (either not installed or not a recognized platform)
|
# Failure (either not installed or not a recognized platform)
|
||||||
raise DMError("Failed to get application root for: %s" % packageName)
|
raise DMError("Failed to get application root for: %s" % packageName)
|
||||||
@ -674,27 +665,28 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
|
|
||||||
returns: returncode from subprocess.Popen
|
returns: returncode from subprocess.Popen
|
||||||
"""
|
"""
|
||||||
finalArgs = [self.adbPath]
|
finalArgs = [self._adbPath]
|
||||||
if self.deviceSerial:
|
if self._deviceSerial:
|
||||||
finalArgs.extend(['-s', self.deviceSerial])
|
finalArgs.extend(['-s', self._deviceSerial])
|
||||||
# use run-as to execute commands as the package we're testing if
|
# use run-as to execute commands as the package we're testing if
|
||||||
# possible
|
# possible
|
||||||
if not self.haveRootShell and self.useRunAs and args[0] == "shell" and args[1] != "run-as":
|
if not self._haveRootShell and self._useRunAs and \
|
||||||
|
args[0] == "shell" and args[1] not in [ "run-as", "am" ]:
|
||||||
args.insert(1, "run-as")
|
args.insert(1, "run-as")
|
||||||
args.insert(2, self.packageName)
|
args.insert(2, self._packageName)
|
||||||
finalArgs.extend(args)
|
finalArgs.extend(args)
|
||||||
return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
return subprocess.Popen(finalArgs, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
|
||||||
def _runCmdAs(self, args):
|
def _runCmdAs(self, args):
|
||||||
"""
|
"""
|
||||||
Runs a command using adb
|
Runs a command using adb
|
||||||
If self.useRunAs is True, the command is run-as user specified in self.packageName
|
If self._useRunAs is True, the command is run-as user specified in self._packageName
|
||||||
|
|
||||||
returns: returncode from subprocess.Popen
|
returns: returncode from subprocess.Popen
|
||||||
"""
|
"""
|
||||||
if self.useRunAs:
|
if self._useRunAs:
|
||||||
args.insert(1, "run-as")
|
args.insert(1, "run-as")
|
||||||
args.insert(2, self.packageName)
|
args.insert(2, self._packageName)
|
||||||
return self._runCmd(args)
|
return self._runCmd(args)
|
||||||
|
|
||||||
# timeout is specified in seconds, and if no timeout is given,
|
# timeout is specified in seconds, and if no timeout is given,
|
||||||
@ -708,12 +700,13 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
"""
|
"""
|
||||||
# use run-as to execute commands as the package we're testing if
|
# use run-as to execute commands as the package we're testing if
|
||||||
# possible
|
# possible
|
||||||
finalArgs = [self.adbPath]
|
finalArgs = [self._adbPath]
|
||||||
if self.deviceSerial:
|
if self._deviceSerial:
|
||||||
finalArgs.extend(['-s', self.deviceSerial])
|
finalArgs.extend(['-s', self._deviceSerial])
|
||||||
if not self.haveRootShell and self.useRunAs and args[0] == "shell" and args[1] != "run-as":
|
if not self._haveRootShell and self._useRunAs and \
|
||||||
|
args[0] == "shell" and args[1] not in [ "run-as", "am" ]:
|
||||||
args.insert(1, "run-as")
|
args.insert(1, "run-as")
|
||||||
args.insert(2, self.packageName)
|
args.insert(2, self._packageName)
|
||||||
finalArgs.extend(args)
|
finalArgs.extend(args)
|
||||||
if not timeout:
|
if not timeout:
|
||||||
# We are asserting that all commands will complete in this time unless otherwise specified
|
# We are asserting that all commands will complete in this time unless otherwise specified
|
||||||
@ -724,7 +717,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
ret_code = proc.poll()
|
ret_code = proc.poll()
|
||||||
while ((time.time() - start_time) <= timeout) and ret_code == None:
|
while ((time.time() - start_time) <= timeout) and ret_code == None:
|
||||||
time.sleep(self.pollingInterval)
|
time.sleep(self._pollingInterval)
|
||||||
ret_code = proc.poll()
|
ret_code = proc.poll()
|
||||||
if ret_code == None:
|
if ret_code == None:
|
||||||
proc.kill()
|
proc.kill()
|
||||||
@ -734,14 +727,14 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
def _checkCmdAs(self, args, timeout=None):
|
def _checkCmdAs(self, args, timeout=None):
|
||||||
"""
|
"""
|
||||||
Runs a command using adb and waits for command to finish
|
Runs a command using adb and waits for command to finish
|
||||||
If self.useRunAs is True, the command is run-as user specified in self.packageName
|
If self._useRunAs is True, the command is run-as user specified in self._packageName
|
||||||
If timeout is specified, the process is killed after <timeout> seconds
|
If timeout is specified, the process is killed after <timeout> seconds
|
||||||
|
|
||||||
returns: returncode from subprocess.Popen
|
returns: returncode from subprocess.Popen
|
||||||
"""
|
"""
|
||||||
if (self.useRunAs):
|
if (self._useRunAs):
|
||||||
args.insert(1, "run-as")
|
args.insert(1, "run-as")
|
||||||
args.insert(2, self.packageName)
|
args.insert(2, self._packageName)
|
||||||
return self._checkCmd(args, timeout)
|
return self._checkCmd(args, timeout)
|
||||||
|
|
||||||
def chmodDir(self, remoteDir, mask="777"):
|
def chmodDir(self, remoteDir, mask="777"):
|
||||||
@ -767,9 +760,9 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
"""
|
"""
|
||||||
Check to see if adb itself can be executed.
|
Check to see if adb itself can be executed.
|
||||||
"""
|
"""
|
||||||
if self.adbPath != 'adb':
|
if self._adbPath != 'adb':
|
||||||
if not os.access(self.adbPath, os.X_OK):
|
if not os.access(self._adbPath, os.X_OK):
|
||||||
raise DMError("invalid adb path, or adb not executable: %s", self.adbPath)
|
raise DMError("invalid adb path, or adb not executable: %s", self._adbPath)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._checkCmd(["version"])
|
self._checkCmd(["version"])
|
||||||
@ -780,20 +773,20 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
|
|
||||||
def _verifyDevice(self):
|
def _verifyDevice(self):
|
||||||
# If there is a device serial number, see if adb is connected to it
|
# If there is a device serial number, see if adb is connected to it
|
||||||
if self.deviceSerial:
|
if self._deviceSerial:
|
||||||
deviceStatus = None
|
deviceStatus = None
|
||||||
proc = subprocess.Popen([self.adbPath, "devices"],
|
proc = subprocess.Popen([self._adbPath, "devices"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.STDOUT)
|
stderr=subprocess.STDOUT)
|
||||||
for line in proc.stdout:
|
for line in proc.stdout:
|
||||||
m = re.match('(.+)?\s+(.+)$', line)
|
m = re.match('(.+)?\s+(.+)$', line)
|
||||||
if m:
|
if m:
|
||||||
if self.deviceSerial == m.group(1):
|
if self._deviceSerial == m.group(1):
|
||||||
deviceStatus = m.group(2)
|
deviceStatus = m.group(2)
|
||||||
if deviceStatus == None:
|
if deviceStatus == None:
|
||||||
raise DMError("device not found: %s" % self.deviceSerial)
|
raise DMError("device not found: %s" % self._deviceSerial)
|
||||||
elif deviceStatus != "device":
|
elif deviceStatus != "device":
|
||||||
raise DMError("bad status for device %s: %s" % (self.deviceSerial, deviceStatus))
|
raise DMError("bad status for device %s: %s" % (self._deviceSerial, deviceStatus))
|
||||||
|
|
||||||
# Check to see if we can connect to device and run a simple command
|
# Check to see if we can connect to device and run a simple command
|
||||||
try:
|
try:
|
||||||
@ -814,7 +807,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
data = self._runCmd(["shell", "dd", "-"]).stdout.read()
|
data = self._runCmd(["shell", "dd", "-"]).stdout.read()
|
||||||
if (re.search('unknown operand', data)):
|
if (re.search('unknown operand', data)):
|
||||||
print "'cp' not found, but 'dd' was found as a replacement"
|
print "'cp' not found, but 'dd' was found as a replacement"
|
||||||
self.useDDCopy = True
|
self._useDDCopy = True
|
||||||
return True
|
return True
|
||||||
print "unable to execute 'cp' on device; consider installing busybox from Android Market"
|
print "unable to execute 'cp' on device; consider installing busybox from Android Market"
|
||||||
return False
|
return False
|
||||||
@ -827,28 +820,28 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
# echoing conditions encountered by Fennec at run time.
|
# echoing conditions encountered by Fennec at run time.
|
||||||
# Check to see if run-as can be used here, by verifying a
|
# Check to see if run-as can be used here, by verifying a
|
||||||
# file copy via run-as.
|
# file copy via run-as.
|
||||||
self.useRunAs = False
|
self._useRunAs = False
|
||||||
devroot = self.getDeviceRoot()
|
devroot = self.getDeviceRoot()
|
||||||
if (self.packageName and self._isCpAvailable() and devroot):
|
if (self._packageName and self._isCpAvailable() and devroot):
|
||||||
tmpDir = self.getTempDir()
|
tmpDir = self.getTempDir()
|
||||||
|
|
||||||
# The problem here is that run-as doesn't cause a non-zero exit code
|
# The problem here is that run-as doesn't cause a non-zero exit code
|
||||||
# when failing because of a non-existent or non-debuggable package :(
|
# when failing because of a non-existent or non-debuggable package :(
|
||||||
runAsOut = self._runCmd(["shell", "run-as", self.packageName, "mkdir", devroot + "/sanity"]).communicate()[0]
|
runAsOut = self._runCmd(["shell", "run-as", self._packageName, "mkdir", devroot + "/sanity"]).communicate()[0]
|
||||||
if runAsOut.startswith("run-as:") and ("not debuggable" in runAsOut or "is unknown" in runAsOut):
|
if runAsOut.startswith("run-as:") and ("not debuggable" in runAsOut or "is unknown" in runAsOut):
|
||||||
raise DMError("run-as failed sanity check")
|
raise DMError("run-as failed sanity check")
|
||||||
|
|
||||||
tmpfile = tempfile.NamedTemporaryFile()
|
tmpfile = tempfile.NamedTemporaryFile()
|
||||||
self._checkCmd(["push", tmpfile.name, tmpDir + "/tmpfile"])
|
self._checkCmd(["push", tmpfile.name, tmpDir + "/tmpfile"])
|
||||||
if self.useDDCopy:
|
if self._useDDCopy:
|
||||||
self._checkCmd(["shell", "run-as", self.packageName, "dd", "if=" + tmpDir + "/tmpfile", "of=" + devroot + "/sanity/tmpfile"])
|
self._checkCmd(["shell", "run-as", self._packageName, "dd", "if=" + tmpDir + "/tmpfile", "of=" + devroot + "/sanity/tmpfile"])
|
||||||
else:
|
else:
|
||||||
self._checkCmd(["shell", "run-as", self.packageName, "cp", tmpDir + "/tmpfile", devroot + "/sanity"])
|
self._checkCmd(["shell", "run-as", self._packageName, "cp", tmpDir + "/tmpfile", devroot + "/sanity"])
|
||||||
if (self.fileExists(devroot + "/sanity/tmpfile")):
|
if (self.fileExists(devroot + "/sanity/tmpfile")):
|
||||||
print "will execute commands via run-as " + self.packageName
|
print "will execute commands via run-as " + self._packageName
|
||||||
self.useRunAs = True
|
self._useRunAs = True
|
||||||
self._checkCmd(["shell", "rm", devroot + "/tmp/tmpfile"])
|
self._checkCmd(["shell", "rm", devroot + "/tmp/tmpfile"])
|
||||||
self._checkCmd(["shell", "run-as", self.packageName, "rm", "-r", devroot + "/sanity"])
|
self._checkCmd(["shell", "run-as", self._packageName, "rm", "-r", devroot + "/sanity"])
|
||||||
|
|
||||||
def _checkForRoot(self):
|
def _checkForRoot(self):
|
||||||
# Check whether we _are_ root by default (some development boards work
|
# Check whether we _are_ root by default (some development boards work
|
||||||
@ -857,7 +850,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
proc = self._runCmd(["shell", "id"])
|
proc = self._runCmd(["shell", "id"])
|
||||||
data = proc.stdout.read()
|
data = proc.stdout.read()
|
||||||
if data.find('uid=0(root)') >= 0:
|
if data.find('uid=0(root)') >= 0:
|
||||||
self.haveRootShell = True
|
self._haveRootShell = True
|
||||||
# if this returns true, we don't care about su
|
# if this returns true, we don't care about su
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -876,7 +869,7 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
|
|
||||||
data = proc.stdout.read()
|
data = proc.stdout.read()
|
||||||
if data.find('uid=0(root)') >= 0:
|
if data.find('uid=0(root)') >= 0:
|
||||||
self.haveSu = True
|
self._haveSu = True
|
||||||
|
|
||||||
def _isUnzipAvailable(self):
|
def _isUnzipAvailable(self):
|
||||||
data = self._runCmdAs(["shell", "unzip"]).stdout.read()
|
data = self._runCmdAs(["shell", "unzip"]).stdout.read()
|
||||||
@ -896,9 +889,9 @@ class DeviceManagerADB(DeviceManager):
|
|||||||
# If "zip" can be run locally, and "unzip" can be run remotely, then pushDir
|
# If "zip" can be run locally, and "unzip" can be run remotely, then pushDir
|
||||||
# can use these to push just one file per directory -- a significant
|
# can use these to push just one file per directory -- a significant
|
||||||
# optimization for large directories.
|
# optimization for large directories.
|
||||||
self.useZip = False
|
self._useZip = False
|
||||||
if (self._isUnzipAvailable() and self._isLocalZipAvailable()):
|
if (self._isUnzipAvailable() and self._isLocalZipAvailable()):
|
||||||
print "will use zip to push directories"
|
print "will use zip to push directories"
|
||||||
self.useZip = True
|
self._useZip = True
|
||||||
else:
|
else:
|
||||||
raise DMError("zip not available")
|
raise DMError("zip not available")
|
||||||
|
@ -18,11 +18,11 @@ from distutils.version import StrictVersion
|
|||||||
|
|
||||||
class DeviceManagerSUT(DeviceManager):
|
class DeviceManagerSUT(DeviceManager):
|
||||||
debug = 2
|
debug = 2
|
||||||
base_prompt = '$>'
|
_base_prompt = '$>'
|
||||||
base_prompt_re = '\$\>'
|
_base_prompt_re = '\$\>'
|
||||||
prompt_sep = '\x00'
|
_prompt_sep = '\x00'
|
||||||
prompt_regex = '.*(' + base_prompt_re + prompt_sep + ')'
|
_prompt_regex = '.*(' + _base_prompt_re + _prompt_sep + ')'
|
||||||
agentErrorRE = re.compile('^##AGENT-WARNING##\ ?(.*)')
|
_agentErrorRE = re.compile('^##AGENT-WARNING##\ ?(.*)')
|
||||||
default_timeout = 300
|
default_timeout = 300
|
||||||
|
|
||||||
def __init__(self, host, port = 20701, retrylimit = 5, deviceRoot = None, **kwargs):
|
def __init__(self, host, port = 20701, retrylimit = 5, deviceRoot = None, **kwargs):
|
||||||
@ -61,7 +61,7 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
"""
|
"""
|
||||||
take a data blob and strip instances of the prompt '$>\x00'
|
take a data blob and strip instances of the prompt '$>\x00'
|
||||||
"""
|
"""
|
||||||
promptre = re.compile(self.prompt_regex + '.*')
|
promptre = re.compile(self._prompt_regex + '.*')
|
||||||
retVal = []
|
retVal = []
|
||||||
lines = data.split('\n')
|
lines = data.split('\n')
|
||||||
for line in lines:
|
for line in lines:
|
||||||
@ -69,10 +69,10 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
try:
|
try:
|
||||||
while (promptre.match(line)):
|
while (promptre.match(line)):
|
||||||
foundPrompt = True
|
foundPrompt = True
|
||||||
pieces = line.split(self.prompt_sep)
|
pieces = line.split(self._prompt_sep)
|
||||||
index = pieces.index('$>')
|
index = pieces.index('$>')
|
||||||
pieces.pop(index)
|
pieces.pop(index)
|
||||||
line = self.prompt_sep.join(pieces)
|
line = self._prompt_sep.join(pieces)
|
||||||
except(ValueError):
|
except(ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
return outputfile.read()
|
return outputfile.read()
|
||||||
|
|
||||||
def _doCmds(self, cmdlist, outputfile, timeout):
|
def _doCmds(self, cmdlist, outputfile, timeout):
|
||||||
promptre = re.compile(self.prompt_regex + '$')
|
promptre = re.compile(self._prompt_regex + '$')
|
||||||
shouldCloseSocket = False
|
shouldCloseSocket = False
|
||||||
|
|
||||||
if not timeout:
|
if not timeout:
|
||||||
@ -242,7 +242,7 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
# If something goes wrong in the agent it will send back a string that
|
# If something goes wrong in the agent it will send back a string that
|
||||||
# starts with '##AGENT-WARNING##'
|
# starts with '##AGENT-WARNING##'
|
||||||
if not commandFailed:
|
if not commandFailed:
|
||||||
errorMatch = self.agentErrorRE.match(data)
|
errorMatch = self._agentErrorRE.match(data)
|
||||||
if errorMatch:
|
if errorMatch:
|
||||||
# We still need to consume the prompt, so raise an error after
|
# We still need to consume the prompt, so raise an error after
|
||||||
# draining the rest of the buffer.
|
# draining the rest of the buffer.
|
||||||
@ -450,11 +450,20 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
for line in data.splitlines():
|
for line in data.splitlines():
|
||||||
if line:
|
if line:
|
||||||
pidproc = line.strip().split()
|
pidproc = line.strip().split()
|
||||||
if (len(pidproc) == 2):
|
try:
|
||||||
processTuples += [[pidproc[0], pidproc[1]]]
|
if (len(pidproc) == 2):
|
||||||
elif (len(pidproc) == 3):
|
processTuples += [[pidproc[0], pidproc[1]]]
|
||||||
#android returns <userID> <procID> <procName>
|
elif (len(pidproc) == 3):
|
||||||
processTuples += [[int(pidproc[1]), pidproc[2], int(pidproc[0])]]
|
# android returns <userID> <procID> <procName>
|
||||||
|
processTuples += [[int(pidproc[1]), pidproc[2], int(pidproc[0])]]
|
||||||
|
else:
|
||||||
|
# unexpected format
|
||||||
|
raise ValueError
|
||||||
|
except ValueError:
|
||||||
|
print "ERROR: Unable to parse process list (bug 805969)"
|
||||||
|
print "Line: %s\nFull output of process list:\n%s" % (line, data)
|
||||||
|
raise DMError("Invalid process line: %s" % line)
|
||||||
|
|
||||||
return processTuples
|
return processTuples
|
||||||
|
|
||||||
def fireProcess(self, appname, failIfRunning=False):
|
def fireProcess(self, appname, failIfRunning=False):
|
||||||
@ -596,7 +605,7 @@ class DeviceManagerSUT(DeviceManager):
|
|||||||
buf += data
|
buf += data
|
||||||
return buf
|
return buf
|
||||||
|
|
||||||
prompt = self.base_prompt + self.prompt_sep
|
prompt = self._base_prompt + self._prompt_sep
|
||||||
buf = ''
|
buf = ''
|
||||||
|
|
||||||
# expected return value:
|
# expected return value:
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
import os
|
import os
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
PACKAGE_VERSION = '0.14'
|
PACKAGE_VERSION = '0.15'
|
||||||
|
|
||||||
# take description from README
|
# take description from README
|
||||||
here = os.path.dirname(os.path.abspath(__file__))
|
here = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
@ -8,6 +8,10 @@ class PsTest(unittest.TestCase):
|
|||||||
"10029 549 com.android.launcher\n"
|
"10029 549 com.android.launcher\n"
|
||||||
"10066 1198 com.twitter.android")]
|
"10066 1198 com.twitter.android")]
|
||||||
|
|
||||||
|
bad_pscommands = [('ps',
|
||||||
|
"abcdef 549 com.android.launcher\n"
|
||||||
|
"10066 1198 com.twitter.android")]
|
||||||
|
|
||||||
def test_processList(self):
|
def test_processList(self):
|
||||||
a = MockAgent(self,
|
a = MockAgent(self,
|
||||||
commands=self.pscommands)
|
commands=self.pscommands)
|
||||||
@ -19,6 +23,20 @@ class PsTest(unittest.TestCase):
|
|||||||
|
|
||||||
a.wait()
|
a.wait()
|
||||||
|
|
||||||
|
def test_badProcessList(self):
|
||||||
|
a = MockAgent(self,
|
||||||
|
commands=self.bad_pscommands)
|
||||||
|
d = mozdevice.DroidSUT("127.0.0.1", port=a.port)
|
||||||
|
exceptionTriggered = False
|
||||||
|
try:
|
||||||
|
d.getProcessList()
|
||||||
|
except mozdevice.DMError:
|
||||||
|
exceptionTriggered = True
|
||||||
|
|
||||||
|
self.assertTrue(exceptionTriggered)
|
||||||
|
|
||||||
|
a.wait()
|
||||||
|
|
||||||
def test_processExist(self):
|
def test_processExist(self):
|
||||||
for i in [('com.android.launcher', 549),
|
for i in [('com.android.launcher', 549),
|
||||||
('com.fennec.android', None)]:
|
('com.fennec.android', None)]:
|
||||||
|
Loading…
Reference in New Issue
Block a user