Bug 1440674 - Simplify some code in remoteautomation.py; r=jmaher

remove RemoteAutomation._product and product options;
remove some unused code paths;
remove "blobber" references;
remove incorrect and/or unhelpful comments;
s/_devicemanager/_dm/ (shorter, improve readability)
This commit is contained in:
Geoff Brown 2018-02-23 09:47:57 -07:00
Родитель c2cb30ae1f
Коммит 385ab244a3
6 изменённых файлов: 40 добавлений и 102 удалений

Просмотреть файл

@ -10,7 +10,6 @@ import os
import posixpath
import tempfile
import shutil
import subprocess
import sys
from automation import Automation
@ -27,25 +26,19 @@ fennecLogcatFilters = [ "The character encoding of the HTML document was not dec
class RemoteAutomation(Automation):
_devicemanager = None
# Part of a hack for Robocop: "am COMMAND" is handled specially if COMMAND
# is in this set. See usages below.
_specialAmCommands = ('instrument', 'start')
def __init__(self, deviceManager, appName = '', remoteLog = None,
processArgs=None):
self._devicemanager = deviceManager
self._dm = deviceManager
self._appName = appName
self._remoteProfile = None
self._remoteLog = remoteLog
self._processArgs = processArgs or {};
# Default our product to fennec
self._product = "fennec"
self.lastTestSeen = "remoteautomation.py"
Automation.__init__(self)
def setDeviceManager(self, deviceManager):
self._devicemanager = deviceManager
self._dm = deviceManager
def setAppName(self, appName):
self._appName = appName
@ -53,9 +46,6 @@ class RemoteAutomation(Automation):
def setRemoteProfile(self, remoteProfile):
self._remoteProfile = remoteProfile
def setProduct(self, product):
self._product = product
def setRemoteLog(self, logfile):
self._remoteLog = logfile
@ -111,7 +101,7 @@ class RemoteAutomation(Automation):
status = proc.wait(timeout = maxTime, noOutputTimeout = timeout)
self.lastTestSeen = proc.getLastTestSeen
topActivity = self._devicemanager.getTopActivity()
topActivity = self._dm.getTopActivity()
if topActivity == proc.procName:
print "Browser unexpectedly found running. Killing..."
proc.kill(True)
@ -133,19 +123,19 @@ class RemoteAutomation(Automation):
# we make it empty and writable so we can test the ANR reporter later
traces = "/data/anr/traces.txt"
try:
self._devicemanager.shellCheckOutput(['echo', '', '>', traces], root=True,
timeout=DeviceManager.short_timeout)
self._devicemanager.shellCheckOutput(['chmod', '666', traces], root=True,
timeout=DeviceManager.short_timeout)
self._dm.shellCheckOutput(['echo', '', '>', traces], root=True,
timeout=DeviceManager.short_timeout)
self._dm.shellCheckOutput(['chmod', '666', traces], root=True,
timeout=DeviceManager.short_timeout)
except DMError:
print "Error deleting %s" % traces
pass
def checkForANRs(self):
traces = "/data/anr/traces.txt"
if self._devicemanager.fileExists(traces):
if self._dm.fileExists(traces):
try:
t = self._devicemanager.pullFile(traces)
t = self._dm.pullFile(traces)
if t:
stripped = t.strip()
if len(stripped) > 0:
@ -161,11 +151,11 @@ class RemoteAutomation(Automation):
print "%s not found" % traces
def deleteTombstones(self):
# delete any existing tombstone files from device
# delete any tombstone files from device
tombstones = "/data/tombstones/*"
try:
self._devicemanager.shellCheckOutput(['rm', '-r', tombstones], root=True,
timeout=DeviceManager.short_timeout)
self._dm.shellCheckOutput(['rm', '-r', tombstones], root=True,
timeout=DeviceManager.short_timeout)
except DMError:
# This may just indicate that the tombstone directory is missing
pass
@ -173,25 +163,23 @@ class RemoteAutomation(Automation):
def checkForTombstones(self):
# pull any tombstones from device and move to MOZ_UPLOAD_DIR
remoteDir = "/data/tombstones"
blobberUploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
if blobberUploadDir:
if not os.path.exists(blobberUploadDir):
os.mkdir(blobberUploadDir)
if self._devicemanager.dirExists(remoteDir):
# copy tombstone files from device to local blobber upload directory
uploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
if uploadDir:
if not os.path.exists(uploadDir):
os.mkdir(uploadDir)
if self._dm.dirExists(remoteDir):
# copy tombstone files from device to local upload directory
try:
self._devicemanager.shellCheckOutput(['chmod', '777', remoteDir], root=True,
timeout=DeviceManager.short_timeout)
self._devicemanager.shellCheckOutput(['chmod', '666', os.path.join(remoteDir, '*')], root=True,
timeout=DeviceManager.short_timeout)
self._devicemanager.getDirectory(remoteDir, blobberUploadDir, False)
self._dm.shellCheckOutput(['chmod', '777', remoteDir], root=True,
timeout=DeviceManager.short_timeout)
self._dm.shellCheckOutput(['chmod', '666', os.path.join(remoteDir, '*')],
root=True, timeout=DeviceManager.short_timeout)
self._dm.getDirectory(remoteDir, uploadDir, False)
except DMError:
# This may just indicate that no tombstone files are present
pass
self.deleteTombstones()
# add a .txt file extension to each tombstone file name, so
# that blobber will upload it
for f in glob.glob(os.path.join(blobberUploadDir, "tombstone_??")):
for f in glob.glob(os.path.join(uploadDir, "tombstone_??")):
# add a unique integer to the file name, in case there are
# multiple tombstones generated with the same name, for
# instance, after multiple robocop tests
@ -209,7 +197,7 @@ class RemoteAutomation(Automation):
self.checkForANRs()
self.checkForTombstones()
logcat = self._devicemanager.getLogcat(filterOutRegexps=fennecLogcatFilters)
logcat = self._dm.getLogcat(filterOutRegexps=fennecLogcatFilters)
javaException = mozcrash.check_for_java_exception(logcat, test_name=self.lastTestSeen)
if javaException:
@ -223,21 +211,17 @@ class RemoteAutomation(Automation):
try:
dumpDir = tempfile.mkdtemp()
remoteCrashDir = posixpath.join(self._remoteProfile, 'minidumps')
if not self._devicemanager.dirExists(remoteCrashDir):
if not self._dm.dirExists(remoteCrashDir):
# If crash reporting is enabled (MOZ_CRASHREPORTER=1), the
# minidumps directory is automatically created when Fennec
# (first) starts, so its lack of presence is a hint that
# something went wrong.
print "Automation Error: No crash directory (%s) found on remote device" % remoteCrashDir
# Whilst no crash was found, the run should still display as a failure
return True
self._devicemanager.getDirectory(remoteCrashDir, dumpDir)
self._dm.getDirectory(remoteCrashDir, dumpDir)
logger = get_default_logger()
if logger is not None:
crashed = mozcrash.log_crashes(logger, dumpDir, symbolsPath, test=self.lastTestSeen)
else:
crashed = Automation.checkForCrashes(self, dumpDir, symbolsPath)
crashed = mozcrash.log_crashes(logger, dumpDir, symbolsPath, test=self.lastTestSeen)
finally:
try:
@ -248,36 +232,28 @@ class RemoteAutomation(Automation):
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
# If remote profile is specified, use that instead
if (self._remoteProfile):
if self._remoteProfile:
profileDir = self._remoteProfile
# Hack for robocop, if app & testURL == None and extraArgs contains the rest of the stuff, lets
# assume extraArgs is all we need
if app == "am" and extraArgs[0] in RemoteAutomation._specialAmCommands:
if app == "am" and extraArgs[0] in ('instrument', 'start'):
return app, extraArgs
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs)
# Remove -foreground if it exists, if it doesn't this just returns
try:
args.remove('-foreground')
except:
pass
#TODO: figure out which platform require NO_EM_RESTART
# return app, ['--environ:NO_EM_RESTART=1'] + args
return app, args
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = None):
if stdout == None or stdout == -1 or stdout == subprocess.PIPE:
stdout = self._remoteLog
return self.RProcess(self._devicemanager, cmd, stdout, stderr, env, cwd, self._appName,
return self.RProcess(self._dm, cmd, self._remoteLog, env, cwd, self._appName,
**self._processArgs)
# be careful here as this inner class doesn't have access to outer class members
class RProcess(object):
# device manager process
dm = None
def __init__(self, dm, cmd, stdout=None, stderr=None, env=None, cwd=None, app=None,
def __init__(self, dm, cmd, stdout=None, env=None, cwd=None, app=None,
messageLogger=None, counts=None):
self.dm = dm
self.stdoutlen = 0
@ -292,20 +268,15 @@ class RemoteAutomation(Automation):
self.counts['fail'] = 0
self.counts['todo'] = 0
if (self.proc is None):
if cmd[0] == 'am':
self.proc = stdout
else:
raise Exception("unable to launch process")
self.procName = cmd[0].split('/')[-1]
if cmd[0] == 'am' and cmd[1] in RemoteAutomation._specialAmCommands:
if self.proc is None:
self.proc = stdout
self.procName = cmd[0].split(posixpath.sep)[-1]
if cmd[0] == 'am' and cmd[1] in ('instrument', 'start'):
self.procName = app
# Setting timeout at 1 hour since on a remote device this takes much longer.
# Temporarily increased to 90 minutes because no more chunks can be created.
self.timeout = 5400
# The benefit of the following sleep is unclear; it was formerly 15 seconds
time.sleep(1)
# Used to buffer log messages until we meet a line break
self.logBuffer = ""

Просмотреть файл

@ -440,14 +440,6 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
dest="devicePort",
help="port of remote device to test")
self.add_argument("--remote-product-name",
action="store",
type=str,
dest="remoteProductName",
default="fennec",
help="Name of product to test - either fennec or firefox, "
"defaults to fennec")
self.add_argument("--remote-webserver",
action="store",
type=str,
@ -503,7 +495,7 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
def validate_remote(self, options, automation):
# Ensure our defaults are set properly for everything we can infer
if not options.remoteTestRoot:
options.remoteTestRoot = automation._devicemanager.deviceRoot + \
options.remoteTestRoot = automation._dm.deviceRoot + \
'/reftest'
options.remoteProfile = options.remoteTestRoot + "/profile"
@ -568,7 +560,7 @@ class RemoteArgumentsParser(ReftestArgumentsParser):
options.httpdPath = os.path.join(options.utilityPath, "components")
if not options.ignoreWindowSize:
parts = automation._devicemanager.getInfo(
parts = automation._dm.getInfo(
'screen')['screen'][0].split()
width = int(parts[0].split(':')[1])
height = int(parts[1].split(':')[1])

Просмотреть файл

@ -202,8 +202,7 @@ class RemoteReftest(RefTest):
localAutomation.BIN_SUFFIX = ".exe"
localAutomation.IS_WIN32 = True
paths = [options.xrePath, localAutomation.DIST_BIN, self.automation._product,
os.path.join('..', self.automation._product)]
paths = [options.xrePath, localAutomation.DIST_BIN]
options.xrePath = self.findPath(paths)
if options.xrePath is None:
print ("ERROR: unable to find xulrunner path for %s, "
@ -415,9 +414,6 @@ def run_test_harness(parser, options):
automation = RemoteAutomation(None)
automation.setDeviceManager(dm)
if options.remoteProductName:
automation.setProduct(options.remoteProductName)
# Set up the defaults and ensure options are set
parser.validate_remote(options, automation)

Просмотреть файл

@ -879,13 +879,6 @@ class AndroidArguments(ArgumentContainer):
"default": 20701,
"help": "port of remote device to test",
}],
[["--remote-product-name"],
{"dest": "remoteProductName",
"default": "fennec",
"help": "The executable's name of remote product to test - either \
fennec or firefox, defaults to fennec",
"suppress": True,
}],
[["--remote-logfile"],
{"dest": "remoteLogFile",
"default": None,

Просмотреть файл

@ -64,11 +64,6 @@ class RobocopTestRunner(MochitestDesktop):
self.options.webServer, self.options.httpPort, self.options.sslPort)
self.localLog = options.logFile
self.localProfile = None
productPieces = self.options.remoteProductName.split('.')
if (productPieces is not None):
self.auto.setProduct(productPieces[0])
else:
self.auto.setProduct(self.options.remoteProductName)
self.auto.setAppName(self.options.remoteappname)
self.certdbNew = True
self.remoteCopyAvailable = True
@ -181,9 +176,7 @@ class RobocopTestRunner(MochitestDesktop):
localAutomation = self.makeLocalAutomation()
paths = [
self.options.xrePath,
localAutomation.DIST_BIN,
self.auto._product,
os.path.join('..', self.auto._product)
localAutomation.DIST_BIN
]
self.options.xrePath = self.findPath(paths)
if self.options.xrePath is None:

Просмотреть файл

@ -118,8 +118,6 @@ class MochiRemote(MochitestDesktop):
paths = [
options.xrePath,
localAutomation.DIST_BIN,
self._automation._product,
os.path.join('..', self._automation._product)
]
options.xrePath = self.findPath(paths)
if options.xrePath is None:
@ -342,11 +340,6 @@ def run_test_harness(parser, options):
log.error("%s is not installed on this device" % expected)
return 1
productPieces = options.remoteProductName.split('.')
if (productPieces is not None):
auto.setProduct(productPieces[0])
else:
auto.setProduct(options.remoteProductName)
auto.setAppName(options.remoteappname)
logParent = os.path.dirname(options.remoteLogFile)