2012-05-21 04:12:37 -07:00
|
|
|
# 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/.
|
2010-03-24 10:51:17 -07:00
|
|
|
|
2014-07-17 00:02:00 -07:00
|
|
|
import base64
|
|
|
|
import json
|
2014-07-11 05:15:29 -07:00
|
|
|
import os
|
|
|
|
import shutil
|
2014-07-17 00:02:00 -07:00
|
|
|
import sys
|
|
|
|
import tempfile
|
|
|
|
import traceback
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
sys.path.insert(
|
|
|
|
0, os.path.abspath(
|
|
|
|
os.path.realpath(
|
|
|
|
os.path.dirname(__file__))))
|
2010-02-25 11:10:39 -08:00
|
|
|
|
|
|
|
from automation import Automation
|
2012-11-12 13:57:13 -08:00
|
|
|
from remoteautomation import RemoteAutomation, fennecLogcatFilters
|
2014-08-13 09:03:00 -07:00
|
|
|
from runtests import Mochitest, MessageLogger
|
2015-04-30 10:47:01 -07:00
|
|
|
from mochitest_options import MochitestArgumentParser
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2015-03-10 06:55:30 -07:00
|
|
|
from manifestparser import TestManifest
|
|
|
|
from manifestparser.filters import chunk_by_slice
|
2013-05-03 10:37:59 -07:00
|
|
|
import devicemanager
|
2013-10-08 12:14:38 -07:00
|
|
|
import mozinfo
|
2013-09-05 09:14:54 -07:00
|
|
|
|
2014-04-16 07:29:39 -07:00
|
|
|
SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
|
2010-02-25 11:10:39 -08:00
|
|
|
class MochiRemote(Mochitest):
|
|
|
|
_automation = None
|
|
|
|
_dm = None
|
2012-01-07 15:41:08 -08:00
|
|
|
localProfile = None
|
2014-07-17 00:02:00 -07:00
|
|
|
logMessages = []
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2014-08-13 09:03:00 -07:00
|
|
|
def __init__(self, automation, devmgr, options):
|
|
|
|
Mochitest.__init__(self, options)
|
|
|
|
|
2010-02-25 11:10:39 -08:00
|
|
|
self._automation = automation
|
|
|
|
self._dm = devmgr
|
2013-09-23 07:47:48 -07:00
|
|
|
self.environment = self._automation.environment
|
2010-05-27 13:02:15 -07:00
|
|
|
self.remoteProfile = options.remoteTestRoot + "/profile"
|
2011-10-06 07:51:03 -07:00
|
|
|
self._automation.setRemoteProfile(self.remoteProfile)
|
2010-02-25 11:10:39 -08:00
|
|
|
self.remoteLog = options.remoteLogFile
|
2012-10-03 08:07:31 -07:00
|
|
|
self.localLog = options.logFile
|
2013-05-16 13:32:52 -07:00
|
|
|
self._automation.deleteANRs()
|
2014-08-11 10:55:28 -07:00
|
|
|
self._automation.deleteTombstones()
|
2014-03-14 11:25:41 -07:00
|
|
|
self.certdbNew = True
|
2014-08-13 15:23:26 -07:00
|
|
|
self.remoteNSPR = os.path.join(options.remoteTestRoot, "nspr")
|
2015-02-13 11:42:02 -08:00
|
|
|
self._dm.removeDir(self.remoteNSPR)
|
|
|
|
self._dm.mkDir(self.remoteNSPR)
|
|
|
|
self.remoteChromeTestDir = os.path.join(
|
|
|
|
options.remoteTestRoot,
|
|
|
|
"chrome")
|
|
|
|
self._dm.removeDir(self.remoteChromeTestDir)
|
|
|
|
self._dm.mkDir(self.remoteChromeTestDir)
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2014-06-03 08:19:28 -07:00
|
|
|
def cleanup(self, options):
|
2012-10-15 07:15:19 -07:00
|
|
|
if self._dm.fileExists(self.remoteLog):
|
|
|
|
self._dm.getFile(self.remoteLog, self.localLog)
|
|
|
|
self._dm.removeFile(self.remoteLog)
|
|
|
|
else:
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.warning(
|
|
|
|
"Unable to retrieve log file (%s) from remote device" %
|
|
|
|
self.remoteLog)
|
2010-02-25 11:10:39 -08:00
|
|
|
self._dm.removeDir(self.remoteProfile)
|
2015-02-13 11:42:02 -08:00
|
|
|
self._dm.removeDir(self.remoteChromeTestDir)
|
2014-09-08 16:23:09 -07:00
|
|
|
# Don't leave an old robotium.config hanging around; the
|
|
|
|
# profile it references was just deleted!
|
|
|
|
deviceRoot = self._dm.getDeviceRoot()
|
|
|
|
self._dm.removeFile(os.path.join(deviceRoot, "robotium.config"))
|
2014-08-27 15:23:29 -07:00
|
|
|
blobberUploadDir = os.environ.get('MOZ_UPLOAD_DIR', None)
|
|
|
|
if blobberUploadDir:
|
|
|
|
self._dm.getDirectory(self.remoteNSPR, blobberUploadDir)
|
2014-06-03 08:19:28 -07:00
|
|
|
Mochitest.cleanup(self, options)
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
def findPath(self, paths, filename=None):
|
2010-06-24 02:32:01 -07:00
|
|
|
for path in paths:
|
|
|
|
p = path
|
|
|
|
if filename:
|
|
|
|
p = os.path.join(p, filename)
|
|
|
|
if os.path.exists(self.getFullPath(p)):
|
|
|
|
return path
|
|
|
|
return None
|
2010-05-27 13:02:15 -07:00
|
|
|
|
2014-03-14 11:25:41 -07:00
|
|
|
def makeLocalAutomation(self):
|
2010-06-24 02:32:01 -07:00
|
|
|
localAutomation = Automation()
|
2011-02-24 11:45:42 -08:00
|
|
|
localAutomation.IS_WIN32 = False
|
|
|
|
localAutomation.IS_LINUX = False
|
|
|
|
localAutomation.IS_MAC = False
|
|
|
|
localAutomation.UNIXISH = False
|
|
|
|
hostos = sys.platform
|
2015-02-13 11:42:02 -08:00
|
|
|
if (hostos == 'mac' or hostos == 'darwin'):
|
2014-03-14 11:25:41 -07:00
|
|
|
localAutomation.IS_MAC = True
|
2011-02-24 11:45:42 -08:00
|
|
|
elif (hostos == 'linux' or hostos == 'linux2'):
|
2014-03-14 11:25:41 -07:00
|
|
|
localAutomation.IS_LINUX = True
|
|
|
|
localAutomation.UNIXISH = True
|
2011-02-24 11:45:42 -08:00
|
|
|
elif (hostos == 'win32' or hostos == 'win64'):
|
2014-03-14 11:25:41 -07:00
|
|
|
localAutomation.BIN_SUFFIX = ".exe"
|
|
|
|
localAutomation.IS_WIN32 = True
|
|
|
|
return localAutomation
|
|
|
|
|
|
|
|
# This seems kludgy, but this class uses paths from the remote host in the
|
|
|
|
# options, except when calling up to the base class, which doesn't
|
|
|
|
# understand the distinction. This switches out the remote values for local
|
|
|
|
# ones that the base class understands. This is necessary for the web
|
|
|
|
# server, SSL tunnel and profile building functions.
|
|
|
|
def switchToLocalPaths(self, options):
|
|
|
|
""" Set local paths in the options, return a function that will restore remote values """
|
|
|
|
remoteXrePath = options.xrePath
|
|
|
|
remoteProfilePath = options.profilePath
|
|
|
|
remoteUtilityPath = options.utilityPath
|
2010-06-24 02:32:01 -07:00
|
|
|
|
2014-03-14 11:25:41 -07:00
|
|
|
localAutomation = self.makeLocalAutomation()
|
|
|
|
paths = [
|
|
|
|
options.xrePath,
|
|
|
|
localAutomation.DIST_BIN,
|
|
|
|
self._automation._product,
|
|
|
|
os.path.join('..', self._automation._product)
|
|
|
|
]
|
2010-06-24 02:32:01 -07:00
|
|
|
options.xrePath = self.findPath(paths)
|
2015-02-13 11:42:02 -08:00
|
|
|
if options.xrePath is None:
|
|
|
|
self.log.error(
|
|
|
|
"unable to find xulrunner path for %s, please specify with --xre-path" %
|
|
|
|
os.name)
|
2010-06-24 02:32:01 -07:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
xpcshell = "xpcshell"
|
|
|
|
if (os.name == "nt"):
|
|
|
|
xpcshell += ".exe"
|
2014-03-14 11:25:41 -07:00
|
|
|
|
2013-09-12 08:02:48 -07:00
|
|
|
if options.utilityPath:
|
|
|
|
paths = [options.utilityPath, options.xrePath]
|
|
|
|
else:
|
|
|
|
paths = [options.xrePath]
|
2010-06-24 02:32:01 -07:00
|
|
|
options.utilityPath = self.findPath(paths, xpcshell)
|
2014-03-14 11:25:41 -07:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
if options.utilityPath is None:
|
|
|
|
self.log.error(
|
|
|
|
"unable to find utility path for %s, please specify with --utility-path" %
|
|
|
|
os.name)
|
2010-06-24 02:32:01 -07:00
|
|
|
sys.exit(1)
|
|
|
|
|
2013-01-25 11:35:15 -08:00
|
|
|
xpcshell_path = os.path.join(options.utilityPath, xpcshell)
|
|
|
|
if localAutomation.elf_arm(xpcshell_path):
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.error('xpcshell at %s is an ARM binary; please use '
|
2015-02-13 11:42:02 -08:00
|
|
|
'the --utility-path argument to specify the path '
|
|
|
|
'to a desktop version.' % xpcshell_path)
|
2013-09-05 09:14:56 -07:00
|
|
|
sys.exit(1)
|
2013-01-25 11:35:15 -08:00
|
|
|
|
2012-01-07 15:41:08 -08:00
|
|
|
if self.localProfile:
|
|
|
|
options.profilePath = self.localProfile
|
2014-03-14 11:25:41 -07:00
|
|
|
else:
|
2014-06-23 02:24:00 -07:00
|
|
|
options.profilePath = None
|
2014-03-14 11:25:41 -07:00
|
|
|
|
|
|
|
def fixup():
|
|
|
|
options.xrePath = remoteXrePath
|
|
|
|
options.utilityPath = remoteUtilityPath
|
|
|
|
options.profilePath = remoteProfilePath
|
|
|
|
|
|
|
|
return fixup
|
|
|
|
|
|
|
|
def startServers(self, options, debuggerInfo):
|
|
|
|
""" Create the servers on the host and start them up """
|
|
|
|
restoreRemotePaths = self.switchToLocalPaths(options)
|
2014-12-13 03:09:00 -08:00
|
|
|
# ignoreSSLTunnelExts is a workaround for bug 1109310
|
2015-02-13 11:42:02 -08:00
|
|
|
Mochitest.startServers(
|
|
|
|
self,
|
|
|
|
options,
|
|
|
|
debuggerInfo,
|
|
|
|
ignoreSSLTunnelExts=True)
|
2014-03-14 11:25:41 -07:00
|
|
|
restoreRemotePaths()
|
|
|
|
|
|
|
|
def buildProfile(self, options):
|
|
|
|
restoreRemotePaths = self.switchToLocalPaths(options)
|
2010-02-25 11:10:39 -08:00
|
|
|
manifest = Mochitest.buildProfile(self, options)
|
|
|
|
self.localProfile = options.profilePath
|
2012-01-06 05:37:54 -08:00
|
|
|
self._dm.removeDir(self.remoteProfile)
|
2012-12-28 04:18:22 -08:00
|
|
|
|
|
|
|
# we do not need this for robotium based tests, lets save a LOT of time
|
2013-05-20 11:39:50 -07:00
|
|
|
if options.robocopIni:
|
2012-12-28 04:18:22 -08:00
|
|
|
shutil.rmtree(os.path.join(options.profilePath, 'webapps'))
|
2015-02-13 11:42:02 -08:00
|
|
|
shutil.rmtree(
|
|
|
|
os.path.join(
|
|
|
|
options.profilePath,
|
|
|
|
'extensions',
|
|
|
|
'staged',
|
|
|
|
'mochikit@mozilla.org'))
|
|
|
|
shutil.rmtree(
|
|
|
|
os.path.join(
|
|
|
|
options.profilePath,
|
|
|
|
'extensions',
|
|
|
|
'staged',
|
|
|
|
'worker-test@mozilla.org'))
|
|
|
|
shutil.rmtree(
|
|
|
|
os.path.join(
|
|
|
|
options.profilePath,
|
|
|
|
'extensions',
|
|
|
|
'staged',
|
|
|
|
'workerbootstrap-test@mozilla.org'))
|
2012-12-28 04:18:22 -08:00
|
|
|
os.remove(os.path.join(options.profilePath, 'userChrome.css'))
|
|
|
|
|
Bug 795496 - Make mozdevice raise exceptions on error;r=ahal,jmaher
It turns out that relying on the user to check return codes for every
command was non-intuitive and resulted in many hard to trace bugs.
Now most functinos just return "None", and raise a DMError when there's an
exception. The exception to this are functions like dirExists, which now return
booleans, and throw exceptions on error. This is a fairly major refactor,
and also involved the following internal changes:
* Removed FileError and AgentError exceptions, replaced with DMError
(having to manage three different types of exceptions was confusing,
all the more so when we're raising them)
* Docstrings updated to remove references to return values where no
longer relevant
* pushFile no longer will create a directory to accomodate the file
if it doesn't exist (this makes it consistent with devicemanagerADB)
* dmSUT we validate the file, but assume that we get something back
from the agent, instead of falling back to manual validation in the
case that we didn't
* isDir and dirExists had the same intention, but different
implementations for dmSUT. Replaced the dmSUT impl of getDirectory
with that of isDir's (which was much simpler). Removed
isDir from devicemanager.py, since it wasn't used externally
* killProcess modified to check for process existence before running
(since the actual internal kill command will throw an exception
if the process doesn't exist)
In addition to all this, more unit tests have been added to test these
changes for devicemanagerSUT.
2012-10-04 08:28:07 -07:00
|
|
|
try:
|
|
|
|
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
|
|
|
except devicemanager.DMError:
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.error(
|
|
|
|
"Automation Error: Unable to copy profile to device.")
|
Bug 795496 - Make mozdevice raise exceptions on error;r=ahal,jmaher
It turns out that relying on the user to check return codes for every
command was non-intuitive and resulted in many hard to trace bugs.
Now most functinos just return "None", and raise a DMError when there's an
exception. The exception to this are functions like dirExists, which now return
booleans, and throw exceptions on error. This is a fairly major refactor,
and also involved the following internal changes:
* Removed FileError and AgentError exceptions, replaced with DMError
(having to manage three different types of exceptions was confusing,
all the more so when we're raising them)
* Docstrings updated to remove references to return values where no
longer relevant
* pushFile no longer will create a directory to accomodate the file
if it doesn't exist (this makes it consistent with devicemanagerADB)
* dmSUT we validate the file, but assume that we get something back
from the agent, instead of falling back to manual validation in the
case that we didn't
* isDir and dirExists had the same intention, but different
implementations for dmSUT. Replaced the dmSUT impl of getDirectory
with that of isDir's (which was much simpler). Removed
isDir from devicemanager.py, since it wasn't used externally
* killProcess modified to check for process existence before running
(since the actual internal kill command will throw an exception
if the process doesn't exist)
In addition to all this, more unit tests have been added to test these
changes for devicemanagerSUT.
2012-10-04 08:28:07 -07:00
|
|
|
raise
|
2010-03-15 15:47:34 -07:00
|
|
|
|
2014-03-14 11:25:41 -07:00
|
|
|
restoreRemotePaths()
|
2010-02-25 11:10:39 -08:00
|
|
|
options.profilePath = self.remoteProfile
|
|
|
|
return manifest
|
2014-03-14 11:25:41 -07:00
|
|
|
|
2011-07-26 16:13:20 -07:00
|
|
|
def buildURLOptions(self, options, env):
|
2010-02-25 11:10:39 -08:00
|
|
|
self.localLog = options.logFile
|
|
|
|
options.logFile = self.remoteLog
|
2014-08-15 12:42:00 -07:00
|
|
|
options.fileLevel = 'INFO'
|
2010-11-04 17:01:12 -07:00
|
|
|
options.profilePath = self.localProfile
|
2012-12-07 08:04:01 -08:00
|
|
|
env["MOZ_HIDE_RESULTS_TABLE"] = "1"
|
2011-07-26 16:13:20 -07:00
|
|
|
retVal = Mochitest.buildURLOptions(self, options, env)
|
2012-12-28 04:18:22 -08:00
|
|
|
|
2013-05-20 11:39:50 -07:00
|
|
|
if not options.robocopIni:
|
2015-02-13 11:42:02 -08:00
|
|
|
# we really need testConfig.js (for browser chrome)
|
2012-12-28 04:18:22 -08:00
|
|
|
try:
|
|
|
|
self._dm.pushDir(options.profilePath, self.remoteProfile)
|
|
|
|
except devicemanager.DMError:
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.error(
|
|
|
|
"Automation Error: Unable to copy profile to device.")
|
2012-12-28 04:18:22 -08:00
|
|
|
raise
|
2010-11-04 17:01:12 -07:00
|
|
|
|
|
|
|
options.profilePath = self.remoteProfile
|
2010-02-25 11:10:39 -08:00
|
|
|
options.logFile = self.localLog
|
|
|
|
return retVal
|
|
|
|
|
2014-07-15 14:55:00 -07:00
|
|
|
def getTestsToRun(self, options):
|
|
|
|
if options.robocopIni != "":
|
|
|
|
# Skip over tests filtering if we run robocop tests.
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return super(MochiRemote, self).getTestsToRun(options)
|
|
|
|
|
2014-07-04 04:55:00 -07:00
|
|
|
def buildTestPath(self, options, testsToFilter=None):
|
2014-03-18 08:03:51 -07:00
|
|
|
if options.robocopIni != "":
|
|
|
|
# Skip over manifest building if we just want to run
|
|
|
|
# robocop tests.
|
|
|
|
return self.buildTestURL(options)
|
|
|
|
else:
|
2015-02-13 11:42:02 -08:00
|
|
|
return super(
|
|
|
|
MochiRemote,
|
|
|
|
self).buildTestPath(
|
|
|
|
options,
|
|
|
|
testsToFilter)
|
2014-03-18 08:03:51 -07:00
|
|
|
|
2014-11-26 15:51:14 -08:00
|
|
|
def getChromeTestDir(self, options):
|
|
|
|
local = super(MochiRemote, self).getChromeTestDir(options)
|
|
|
|
local = os.path.join(local, "chrome")
|
|
|
|
remote = self.remoteChromeTestDir
|
|
|
|
if options.chrome:
|
|
|
|
self.log.info("pushing %s to %s on device..." % (local, remote))
|
|
|
|
self._dm.pushDir(local, remote)
|
|
|
|
return remote
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2014-03-14 11:25:41 -07:00
|
|
|
def getLogFilePath(self, logFile):
|
2010-02-25 11:10:39 -08:00
|
|
|
return logFile
|
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
# In the future we could use LogParser:
|
|
|
|
# http://hg.mozilla.org/automation/logparser/
|
2012-02-09 05:49:00 -08:00
|
|
|
def addLogData(self):
|
|
|
|
with open(self.localLog) as currentLog:
|
|
|
|
data = currentLog.readlines()
|
|
|
|
start_found = False
|
|
|
|
end_found = False
|
2013-01-10 01:24:58 -08:00
|
|
|
fail_found = False
|
2012-02-09 05:49:00 -08:00
|
|
|
for line in data:
|
2014-07-17 00:02:00 -07:00
|
|
|
try:
|
|
|
|
message = json.loads(line)
|
2015-03-24 14:42:24 -07:00
|
|
|
if not isinstance(message, dict) or 'action' not in message:
|
2014-07-17 00:02:00 -07:00
|
|
|
continue
|
|
|
|
except ValueError:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if message['action'] == 'test_end':
|
2012-02-09 05:49:00 -08:00
|
|
|
end_found = True
|
|
|
|
start_found = False
|
2013-01-10 01:24:58 -08:00
|
|
|
break
|
2012-02-09 05:49:00 -08:00
|
|
|
|
|
|
|
if start_found and not end_found:
|
2014-07-17 00:02:00 -07:00
|
|
|
self.logMessages.append(message)
|
2012-02-09 05:49:00 -08:00
|
|
|
|
2014-07-17 00:02:00 -07:00
|
|
|
if message['action'] == 'test_start':
|
2012-02-09 05:49:00 -08:00
|
|
|
start_found = True
|
2014-07-17 00:02:00 -07:00
|
|
|
if 'expected' in message:
|
2013-01-10 01:24:58 -08:00
|
|
|
fail_found = True
|
|
|
|
result = 0
|
|
|
|
if fail_found:
|
|
|
|
result = 1
|
|
|
|
if not end_found:
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.info(
|
|
|
|
"PROCESS-CRASH | Automation Error: Missing end of test marker (process crashed?)")
|
2013-01-10 01:24:58 -08:00
|
|
|
result = 1
|
|
|
|
return result
|
2012-02-09 05:49:00 -08:00
|
|
|
|
|
|
|
def printLog(self):
|
|
|
|
passed = 0
|
|
|
|
failed = 0
|
|
|
|
todo = 0
|
|
|
|
incr = 1
|
2014-03-14 11:25:41 -07:00
|
|
|
logFile = []
|
2012-02-09 05:49:00 -08:00
|
|
|
logFile.append("0 INFO SimpleTest START")
|
2014-07-17 00:02:00 -07:00
|
|
|
for message in self.logMessages:
|
|
|
|
if 'status' not in message:
|
|
|
|
continue
|
|
|
|
|
|
|
|
if 'expected' in message:
|
2014-07-11 05:15:29 -07:00
|
|
|
failed += 1
|
2014-07-17 00:02:00 -07:00
|
|
|
elif message['status'] == 'PASS':
|
|
|
|
passed += 1
|
|
|
|
elif message['status'] == 'FAIL':
|
2012-02-09 05:49:00 -08:00
|
|
|
todo += 1
|
|
|
|
incr += 1
|
|
|
|
|
|
|
|
logFile.append("%s INFO TEST-START | Shutdown" % incr)
|
|
|
|
incr += 1
|
|
|
|
logFile.append("%s INFO Passed: %s" % (incr, passed))
|
|
|
|
incr += 1
|
|
|
|
logFile.append("%s INFO Failed: %s" % (incr, failed))
|
|
|
|
incr += 1
|
|
|
|
logFile.append("%s INFO Todo: %s" % (incr, todo))
|
|
|
|
incr += 1
|
|
|
|
logFile.append("%s INFO SimpleTest FINISHED" % incr)
|
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
# TODO: Consider not printing to stdout because we might be duplicating
|
|
|
|
# output
|
2012-02-09 05:49:00 -08:00
|
|
|
print '\n'.join(logFile)
|
|
|
|
with open(self.localLog, 'w') as localLog:
|
|
|
|
localLog.write('\n'.join(logFile))
|
|
|
|
|
|
|
|
if failed > 0:
|
|
|
|
return 1
|
|
|
|
return 0
|
2012-10-16 10:25:23 -07:00
|
|
|
|
2013-09-27 14:04:16 -07:00
|
|
|
def printScreenshots(self, screenShotDir):
|
|
|
|
# TODO: This can be re-written after completion of bug 749421
|
|
|
|
if not self._dm.dirExists(screenShotDir):
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.info(
|
|
|
|
"SCREENSHOT: No ScreenShots directory available: " +
|
|
|
|
screenShotDir)
|
2013-09-27 14:04:16 -07:00
|
|
|
return
|
|
|
|
|
|
|
|
printed = 0
|
|
|
|
for name in self._dm.listFiles(screenShotDir):
|
|
|
|
fullName = screenShotDir + "/" + name
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.info("SCREENSHOT: FOUND: [%s]" % fullName)
|
2013-09-27 14:04:16 -07:00
|
|
|
try:
|
|
|
|
image = self._dm.pullFile(fullName)
|
|
|
|
encoded = base64.b64encode(image)
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.info("SCREENSHOT: data:image/jpg;base64,%s" % encoded)
|
2013-09-27 14:04:16 -07:00
|
|
|
printed += 1
|
|
|
|
except:
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.info("SCREENSHOT: Could not be parsed")
|
2013-09-27 14:04:16 -07:00
|
|
|
pass
|
|
|
|
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.info("SCREENSHOT: TOTAL PRINTED: [%s]" % printed)
|
2013-03-26 10:31:23 -07:00
|
|
|
|
2013-06-24 17:15:40 -07:00
|
|
|
def printDeviceInfo(self, printLogcat=False):
|
2012-12-04 07:54:37 -08:00
|
|
|
try:
|
2013-06-24 17:15:40 -07:00
|
|
|
if printLogcat:
|
2015-02-13 11:42:02 -08:00
|
|
|
logcat = self._dm.getLogcat(
|
|
|
|
filterOutRegexps=fennecLogcatFilters)
|
|
|
|
self.log.info(
|
|
|
|
'\n' +
|
|
|
|
''.join(logcat).decode(
|
|
|
|
'utf-8',
|
|
|
|
'replace'))
|
2015-02-27 12:15:00 -08:00
|
|
|
self.log.info("Device info:")
|
|
|
|
devinfo = self._dm.getInfo()
|
|
|
|
for category in devinfo:
|
|
|
|
if type(devinfo[category]) is list:
|
|
|
|
self.log.info(" %s:" % category)
|
|
|
|
for item in devinfo[category]:
|
|
|
|
self.log.info(" %s" % item)
|
|
|
|
else:
|
|
|
|
self.log.info(" %s: %s" % (category, devinfo[category]))
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.info("Test root: %s" % self._dm.deviceRoot)
|
2012-12-04 07:54:37 -08:00
|
|
|
except devicemanager.DMError:
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.warning("Error getting device information")
|
2012-12-04 07:54:37 -08:00
|
|
|
|
2012-10-16 10:25:23 -07:00
|
|
|
def buildRobotiumConfig(self, options, browserEnv):
|
2014-07-11 12:29:30 -07:00
|
|
|
deviceRoot = self._dm.deviceRoot
|
2012-10-16 10:25:23 -07:00
|
|
|
fHandle = tempfile.NamedTemporaryFile(suffix='.config',
|
|
|
|
prefix='robotium-',
|
|
|
|
dir=os.getcwd(),
|
|
|
|
delete=False)
|
|
|
|
fHandle.write("profile=%s\n" % (self.remoteProfile))
|
|
|
|
fHandle.write("logfile=%s\n" % (options.remoteLogFile))
|
|
|
|
fHandle.write("host=http://mochi.test:8888/tests\n")
|
2015-02-13 11:42:02 -08:00
|
|
|
fHandle.write(
|
|
|
|
"rawhost=http://%s:%s/tests\n" %
|
|
|
|
(options.remoteWebServer, options.httpPort))
|
2012-10-16 10:25:23 -07:00
|
|
|
|
|
|
|
if browserEnv:
|
|
|
|
envstr = ""
|
|
|
|
delim = ""
|
|
|
|
for key, value in browserEnv.items():
|
|
|
|
try:
|
|
|
|
value.index(',')
|
2015-02-13 11:42:02 -08:00
|
|
|
self.log.error(
|
|
|
|
"buildRobotiumConfig: browserEnv - Found a ',' in our value, unable to process value. key=%s,value=%s" %
|
|
|
|
(key, value))
|
2014-08-13 09:03:00 -07:00
|
|
|
self.log.error("browserEnv=%s" % browserEnv)
|
2014-07-17 00:02:00 -07:00
|
|
|
except ValueError:
|
2012-10-16 10:25:23 -07:00
|
|
|
envstr += "%s%s=%s" % (delim, key, value)
|
|
|
|
delim = ","
|
|
|
|
|
|
|
|
fHandle.write("envvars=%s\n" % envstr)
|
|
|
|
fHandle.close()
|
|
|
|
|
|
|
|
self._dm.removeFile(os.path.join(deviceRoot, "robotium.config"))
|
2015-02-13 11:42:02 -08:00
|
|
|
self._dm.pushFile(
|
|
|
|
fHandle.name,
|
|
|
|
os.path.join(
|
|
|
|
deviceRoot,
|
|
|
|
"robotium.config"))
|
2012-10-16 10:25:23 -07:00
|
|
|
os.unlink(fHandle.name)
|
|
|
|
|
2014-07-25 04:01:13 -07:00
|
|
|
def getGMPPluginPath(self, options):
|
2015-03-30 19:32:15 -07:00
|
|
|
# TODO: bug 1149374
|
2014-07-25 04:01:13 -07:00
|
|
|
return None
|
|
|
|
|
2013-09-16 11:44:25 -07:00
|
|
|
def buildBrowserEnv(self, options, debugger=False):
|
2015-02-13 11:42:02 -08:00
|
|
|
browserEnv = Mochitest.buildBrowserEnv(
|
|
|
|
self,
|
|
|
|
options,
|
|
|
|
debugger=debugger)
|
2015-05-07 17:49:15 -07:00
|
|
|
# remove desktop environment not used on device
|
|
|
|
if "MOZ_WIN_INHERIT_STD_HANDLES_PRE_VISTA" in browserEnv:
|
|
|
|
del browserEnv["MOZ_WIN_INHERIT_STD_HANDLES_PRE_VISTA"]
|
|
|
|
if "XPCOM_MEM_BLOAT_LOG" in browserEnv:
|
|
|
|
del browserEnv["XPCOM_MEM_BLOAT_LOG"]
|
2014-08-13 15:23:26 -07:00
|
|
|
# override nsprLogs to avoid processing in Mochitest base class
|
|
|
|
self.nsprLogs = None
|
2015-02-13 11:42:02 -08:00
|
|
|
browserEnv["NSPR_LOG_FILE"] = os.path.join(
|
|
|
|
self.remoteNSPR,
|
|
|
|
self.nsprLogName)
|
2012-10-16 10:25:23 -07:00
|
|
|
self.buildRobotiumConfig(options, browserEnv)
|
|
|
|
return browserEnv
|
|
|
|
|
2013-09-23 07:47:48 -07:00
|
|
|
def runApp(self, *args, **kwargs):
|
|
|
|
"""front-end automation.py's `runApp` functionality until FennecRunner is written"""
|
|
|
|
|
|
|
|
# automation.py/remoteautomation `runApp` takes the profile path,
|
|
|
|
# whereas runtest.py's `runApp` takes a mozprofile object.
|
|
|
|
if 'profileDir' not in kwargs and 'profile' in kwargs:
|
|
|
|
kwargs['profileDir'] = kwargs.pop('profile').profile
|
|
|
|
|
2014-03-14 11:25:41 -07:00
|
|
|
# We're handling ssltunnel, so we should lie to automation.py to avoid
|
|
|
|
# it trying to set up ssltunnel as well
|
|
|
|
kwargs['runSSLTunnel'] = False
|
|
|
|
|
2014-07-17 00:02:00 -07:00
|
|
|
if 'quiet' in kwargs:
|
|
|
|
kwargs.pop('quiet')
|
|
|
|
|
2013-09-23 07:47:48 -07:00
|
|
|
return self._automation.runApp(*args, **kwargs)
|
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
|
2015-04-30 10:47:01 -07:00
|
|
|
def run_test_harness(options):
|
2014-08-13 09:03:00 -07:00
|
|
|
message_logger = MessageLogger(logger=None)
|
2014-07-17 00:02:00 -07:00
|
|
|
process_args = {'messageLogger': message_logger}
|
|
|
|
auto = RemoteAutomation(None, "fennec", processArgs=process_args)
|
2014-08-13 09:03:00 -07:00
|
|
|
|
2015-04-30 14:28:14 -07:00
|
|
|
if options is None:
|
|
|
|
raise ValueError("Invalid options specified, use --help for a list of valid options")
|
|
|
|
|
2015-04-30 10:47:01 -07:00
|
|
|
dm = options.dm
|
|
|
|
auto.setDeviceManager(dm)
|
2014-08-13 09:03:00 -07:00
|
|
|
mochitest = MochiRemote(auto, dm, options)
|
|
|
|
|
|
|
|
log = mochitest.log
|
2014-08-29 07:37:17 -07:00
|
|
|
message_logger.logger = log
|
2014-08-13 09:03:00 -07:00
|
|
|
mochitest.message_logger = message_logger
|
|
|
|
|
2010-02-25 11:10:39 -08:00
|
|
|
productPieces = options.remoteProductName.split('.')
|
2015-02-13 11:42:02 -08:00
|
|
|
if (productPieces is not None):
|
2010-06-24 02:32:01 -07:00
|
|
|
auto.setProduct(productPieces[0])
|
2010-02-25 11:10:39 -08:00
|
|
|
else:
|
2010-06-24 02:32:01 -07:00
|
|
|
auto.setProduct(options.remoteProductName)
|
2014-02-02 07:11:22 -08:00
|
|
|
auto.setAppName(options.remoteappname)
|
2010-02-25 11:10:39 -08:00
|
|
|
|
2011-07-07 10:10:52 -07:00
|
|
|
logParent = os.path.dirname(options.remoteLogFile)
|
2015-02-13 11:42:02 -08:00
|
|
|
dm.mkDir(logParent)
|
2010-09-29 16:20:33 -07:00
|
|
|
auto.setRemoteLog(options.remoteLogFile)
|
2010-03-15 15:47:34 -07:00
|
|
|
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
|
2011-02-23 11:38:56 -08:00
|
|
|
|
2013-06-24 17:15:40 -07:00
|
|
|
mochitest.printDeviceInfo()
|
2012-07-25 17:45:36 -07:00
|
|
|
|
2013-10-08 12:14:38 -07:00
|
|
|
# Add Android version (SDK level) to mozinfo so that manifest entries
|
|
|
|
# can be conditional on android_version.
|
|
|
|
androidVersion = dm.shellCheckOutput(['getprop', 'ro.build.version.sdk'])
|
2015-02-13 11:42:02 -08:00
|
|
|
log.info(
|
|
|
|
"Android sdk version '%s'; will use this to filter manifests" %
|
|
|
|
str(androidVersion))
|
2013-10-08 12:14:38 -07:00
|
|
|
mozinfo.info['android_version'] = androidVersion
|
|
|
|
|
2014-07-11 12:29:30 -07:00
|
|
|
deviceRoot = dm.deviceRoot
|
2013-11-13 11:48:10 -08:00
|
|
|
if options.dmdPath:
|
|
|
|
dmdLibrary = "libdmd.so"
|
|
|
|
dmdPathOnDevice = os.path.join(deviceRoot, dmdLibrary)
|
|
|
|
dm.removeFile(dmdPathOnDevice)
|
|
|
|
dm.pushFile(os.path.join(options.dmdPath, dmdLibrary), dmdPathOnDevice)
|
|
|
|
options.dmdPath = deviceRoot
|
|
|
|
|
2013-11-21 08:33:43 -08:00
|
|
|
options.dumpOutputDirectory = deviceRoot
|
|
|
|
|
2011-02-23 11:38:56 -08:00
|
|
|
procName = options.app.split('/')[-1]
|
2014-02-02 07:11:22 -08:00
|
|
|
dm.killProcess(procName)
|
2012-10-24 10:34:33 -07:00
|
|
|
|
2013-05-20 11:39:50 -07:00
|
|
|
if options.robocopIni != "":
|
2014-08-06 10:55:00 -07:00
|
|
|
# turning buffering off as it's not used in robocop
|
|
|
|
message_logger.buffering = False
|
|
|
|
|
2013-04-08 11:34:45 -07:00
|
|
|
# sut may wait up to 300 s for a robocop am process before returning
|
|
|
|
dm.default_timeout = 320
|
2015-03-10 06:55:30 -07:00
|
|
|
mp = TestManifest(strict=False)
|
2012-01-07 15:41:08 -08:00
|
|
|
# TODO: pull this in dynamically
|
2013-05-20 11:39:50 -07:00
|
|
|
mp.read(options.robocopIni)
|
2013-02-21 06:03:02 -08:00
|
|
|
|
2015-03-10 06:55:30 -07:00
|
|
|
filters = []
|
2013-02-21 06:03:02 -08:00
|
|
|
if options.totalChunks:
|
2015-03-10 06:55:30 -07:00
|
|
|
filters.append(
|
|
|
|
chunk_by_slice(options.thisChunk, options.totalChunks))
|
|
|
|
robocop_tests = mp.active_tests(exists=False, filters=filters, **mozinfo.info)
|
2012-01-07 15:41:08 -08:00
|
|
|
|
2012-10-05 17:27:12 -07:00
|
|
|
options.extraPrefs.append('browser.search.suggest.enabled=true')
|
|
|
|
options.extraPrefs.append('browser.search.suggest.prompted=true')
|
2013-10-22 19:34:03 -07:00
|
|
|
options.extraPrefs.append('layout.css.devPixelsPerPx=1.0')
|
2013-03-12 11:32:26 -07:00
|
|
|
options.extraPrefs.append('browser.chrome.dynamictoolbar=false')
|
2014-01-30 10:53:33 -08:00
|
|
|
options.extraPrefs.append('browser.snippets.enabled=false')
|
2014-08-13 14:53:34 -07:00
|
|
|
options.extraPrefs.append('browser.casting.enabled=true')
|
2011-12-31 07:03:36 -08:00
|
|
|
|
2013-05-20 11:39:50 -07:00
|
|
|
if (options.dm_trans == 'adb' and options.robocopApk):
|
2013-10-08 12:14:39 -07:00
|
|
|
dm._checkCmd(["install", "-r", options.robocopApk])
|
2011-12-31 07:03:36 -08:00
|
|
|
|
2012-01-24 06:46:34 -08:00
|
|
|
retVal = None
|
2014-08-06 10:55:00 -07:00
|
|
|
# Filtering tests
|
|
|
|
active_tests = []
|
2011-12-31 07:03:36 -08:00
|
|
|
for test in robocop_tests:
|
2012-01-07 15:41:08 -08:00
|
|
|
if options.testPath and options.testPath != test['name']:
|
|
|
|
continue
|
|
|
|
|
2013-10-08 12:14:39 -07:00
|
|
|
if 'disabled' in test:
|
2015-02-13 11:42:02 -08:00
|
|
|
log.info(
|
|
|
|
'TEST-INFO | skipping %s | %s' %
|
|
|
|
(test['name'], test['disabled']))
|
2013-10-08 12:14:39 -07:00
|
|
|
continue
|
|
|
|
|
2014-08-06 10:55:00 -07:00
|
|
|
active_tests.append(test)
|
|
|
|
|
2014-08-29 07:37:17 -07:00
|
|
|
log.suite_start([t['name'] for t in active_tests])
|
2014-08-06 10:55:00 -07:00
|
|
|
|
|
|
|
for test in active_tests:
|
2015-02-13 11:42:02 -08:00
|
|
|
# When running in a loop, we need to create a fresh profile for
|
|
|
|
# each cycle
|
2013-07-30 05:30:40 -07:00
|
|
|
if mochitest.localProfile:
|
|
|
|
options.profilePath = mochitest.localProfile
|
|
|
|
os.system("rm -Rf %s" % options.profilePath)
|
2014-06-23 02:24:00 -07:00
|
|
|
options.profilePath = None
|
2013-07-30 05:30:40 -07:00
|
|
|
mochitest.localProfile = options.profilePath
|
|
|
|
|
2012-01-07 15:41:08 -08:00
|
|
|
options.app = "am"
|
2015-02-13 11:42:02 -08:00
|
|
|
options.browserArgs = [
|
|
|
|
"instrument",
|
|
|
|
"-w",
|
|
|
|
"-e",
|
|
|
|
"deviceroot",
|
|
|
|
deviceRoot,
|
|
|
|
"-e",
|
|
|
|
"class"]
|
|
|
|
options.browserArgs.append(
|
|
|
|
"org.mozilla.gecko.tests.%s" %
|
|
|
|
test['name'])
|
|
|
|
options.browserArgs.append(
|
|
|
|
"org.mozilla.roboexample.test/org.mozilla.gecko.FennecInstrumentationTestRunner")
|
2014-08-13 15:23:26 -07:00
|
|
|
mochitest.nsprLogName = "nspr-%s.log" % test['name']
|
2012-01-07 15:41:08 -08:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
# If the test is for checking the import from bookmarks then make
|
|
|
|
# sure there is data to import
|
2013-03-18 02:15:17 -07:00
|
|
|
if test['name'] == "testImportFromAndroid":
|
2014-03-14 11:25:41 -07:00
|
|
|
|
2015-02-13 11:42:02 -08:00
|
|
|
# Get the OS so we can run the insert in the apropriate
|
|
|
|
# database and following the correct table schema
|
2013-03-18 02:15:17 -07:00
|
|
|
osInfo = dm.getInfo("os")
|
|
|
|
devOS = " ".join(osInfo['os'])
|
|
|
|
|
|
|
|
if ("pandaboard" in devOS):
|
2015-02-13 11:42:02 -08:00
|
|
|
delete = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
2013-03-18 02:15:17 -07:00
|
|
|
else:
|
2015-02-13 11:42:02 -08:00
|
|
|
delete = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
2013-03-18 02:15:17 -07:00
|
|
|
if (options.dm_trans == "sut"):
|
|
|
|
dm._runCmds([{"cmd": " ".join(delete)}])
|
|
|
|
|
|
|
|
# Insert the bookmarks
|
2015-02-13 11:42:02 -08:00
|
|
|
log.info(
|
|
|
|
"Insert bookmarks in the default android browser database")
|
2013-03-18 02:15:17 -07:00
|
|
|
for i in range(20):
|
2015-02-13 11:42:02 -08:00
|
|
|
if ("pandaboard" in devOS):
|
|
|
|
cmd = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser2.db 'insert or replace into bookmarks(_id,title,url,folder,parent,position) values (" +
|
|
|
|
str(
|
|
|
|
30 +
|
|
|
|
i) +
|
|
|
|
",\"Bookmark" +
|
|
|
|
str(i) +
|
|
|
|
"\",\"http://www.bookmark" +
|
|
|
|
str(i) +
|
|
|
|
".com\",0,1," +
|
|
|
|
str(
|
|
|
|
100 +
|
|
|
|
i) +
|
|
|
|
");'"]
|
|
|
|
else:
|
|
|
|
cmd = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser.db 'insert into bookmarks(title,url,bookmark) values (\"Bookmark" +
|
|
|
|
str(i) +
|
|
|
|
"\",\"http://www.bookmark" +
|
|
|
|
str(i) +
|
|
|
|
".com\",1);'"]
|
|
|
|
if (options.dm_trans == "sut"):
|
|
|
|
dm._runCmds([{"cmd": " ".join(cmd)}])
|
2012-01-07 15:41:08 -08:00
|
|
|
try:
|
2013-09-27 14:04:16 -07:00
|
|
|
screenShotDir = "/mnt/sdcard/Robotium-Screenshots"
|
|
|
|
dm.removeDir(screenShotDir)
|
2012-06-13 11:20:43 -07:00
|
|
|
dm.recordLogcat()
|
2012-11-20 07:24:28 -08:00
|
|
|
result = mochitest.runTests(options)
|
2012-11-21 10:57:11 -08:00
|
|
|
if result != 0:
|
2014-07-17 00:02:00 -07:00
|
|
|
log.error("runTests() exited with code %s" % result)
|
2013-01-10 01:24:58 -08:00
|
|
|
log_result = mochitest.addLogData()
|
|
|
|
if result != 0 or log_result != 0:
|
2013-06-24 17:15:40 -07:00
|
|
|
mochitest.printDeviceInfo(printLogcat=True)
|
2013-09-27 14:04:16 -07:00
|
|
|
mochitest.printScreenshots(screenShotDir)
|
2015-02-13 11:42:02 -08:00
|
|
|
# Ensure earlier failures aren't overwritten by success on this
|
|
|
|
# run
|
2012-11-20 07:24:28 -08:00
|
|
|
if retVal is None or retVal == 0:
|
|
|
|
retVal = result
|
2012-01-07 15:41:08 -08:00
|
|
|
except:
|
2015-02-13 11:42:02 -08:00
|
|
|
log.error(
|
|
|
|
"Automation Error: Exception caught while running tests")
|
2012-11-05 05:03:55 -08:00
|
|
|
traceback.print_exc()
|
2014-03-14 11:25:41 -07:00
|
|
|
mochitest.stopServers()
|
2012-01-11 05:50:10 -08:00
|
|
|
try:
|
2014-06-03 08:19:28 -07:00
|
|
|
mochitest.cleanup(options)
|
2012-10-24 10:34:33 -07:00
|
|
|
except devicemanager.DMError:
|
|
|
|
# device error cleaning up... oh well!
|
2012-01-11 05:50:10 -08:00
|
|
|
pass
|
2012-10-24 10:34:33 -07:00
|
|
|
retVal = 1
|
|
|
|
break
|
2013-03-18 02:15:17 -07:00
|
|
|
finally:
|
|
|
|
# Clean-up added bookmarks
|
|
|
|
if test['name'] == "testImportFromAndroid":
|
|
|
|
if ("pandaboard" in devOS):
|
2015-02-13 11:42:02 -08:00
|
|
|
cmd_del = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser2.db \'delete from bookmarks where _id > 14;\'"]
|
2013-03-18 02:15:17 -07:00
|
|
|
else:
|
2015-02-13 11:42:02 -08:00
|
|
|
cmd_del = [
|
|
|
|
'execsu',
|
|
|
|
'sqlite3',
|
|
|
|
"/data/data/com.android.browser/databases/browser.db \'delete from bookmarks where _id > 14;\'"]
|
2013-03-18 02:15:17 -07:00
|
|
|
if (options.dm_trans == "sut"):
|
|
|
|
dm._runCmds([{"cmd": " ".join(cmd_del)}])
|
2012-01-24 06:46:34 -08:00
|
|
|
if retVal is None:
|
2014-07-17 00:02:00 -07:00
|
|
|
log.warning("No tests run. Did you pass an invalid TEST_PATH?")
|
2012-02-09 05:49:00 -08:00
|
|
|
retVal = 1
|
2012-11-21 10:53:48 -08:00
|
|
|
else:
|
2012-10-24 10:34:33 -07:00
|
|
|
# if we didn't have some kind of error running the tests, make
|
|
|
|
# sure the tests actually passed
|
2013-01-04 10:42:22 -08:00
|
|
|
print "INFO | runtests.py | Test summary: start."
|
2012-11-21 10:53:48 -08:00
|
|
|
overallResult = mochitest.printLog()
|
2013-01-04 10:42:22 -08:00
|
|
|
print "INFO | runtests.py | Test summary: end."
|
2012-11-21 10:53:48 -08:00
|
|
|
if retVal == 0:
|
|
|
|
retVal = overallResult
|
2011-12-31 07:03:36 -08:00
|
|
|
else:
|
2014-08-13 15:23:26 -07:00
|
|
|
mochitest.nsprLogName = "nspr.log"
|
2012-01-11 05:50:10 -08:00
|
|
|
try:
|
2012-10-24 10:34:33 -07:00
|
|
|
dm.recordLogcat()
|
|
|
|
retVal = mochitest.runTests(options)
|
2012-01-11 05:50:10 -08:00
|
|
|
except:
|
2013-09-05 09:14:54 -07:00
|
|
|
log.error("Automation Error: Exception caught while running tests")
|
2012-11-05 05:03:55 -08:00
|
|
|
traceback.print_exc()
|
2014-03-14 11:25:41 -07:00
|
|
|
mochitest.stopServers()
|
2012-10-24 10:34:33 -07:00
|
|
|
try:
|
2014-06-03 08:19:28 -07:00
|
|
|
mochitest.cleanup(options)
|
2012-10-24 10:34:33 -07:00
|
|
|
except devicemanager.DMError:
|
|
|
|
# device error cleaning up... oh well!
|
|
|
|
pass
|
|
|
|
retVal = 1
|
|
|
|
|
2014-09-08 16:23:10 -07:00
|
|
|
mochitest.printDeviceInfo(printLogcat=True)
|
|
|
|
|
2014-07-29 05:11:00 -07:00
|
|
|
message_logger.finish()
|
2012-01-07 15:41:08 -08:00
|
|
|
|
2014-09-08 16:23:11 -07:00
|
|
|
return retVal
|
|
|
|
|
2012-12-04 07:54:37 -08:00
|
|
|
|
2015-04-30 10:47:01 -07:00
|
|
|
def main(args=sys.argv[1:]):
|
|
|
|
parser = MochitestArgumentParser(app='android')
|
|
|
|
options = parser.parse_args(args)
|
|
|
|
|
|
|
|
return run_test_harness(options)
|
|
|
|
|
|
|
|
|
2010-02-25 11:10:39 -08:00
|
|
|
if __name__ == "__main__":
|
2015-04-30 10:47:01 -07:00
|
|
|
sys.exit(main())
|