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-08-13 09:03:00 -07:00
import logging
2014-07-17 00:02:00 -07:00
import math
2014-07-11 05:15:29 -07:00
import os
import re
import shutil
2014-07-17 00:02:00 -07:00
import sys
import tempfile
import traceback
2010-02-25 11:10:39 -08:00
2013-08-26 14:17:51 -07: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
2013-07-26 11:40:04 -07:00
from mochitest_options import MochitestOptions
2014-08-13 09:03:00 -07:00
from mozlog import structured
2010-02-25 11:10:39 -08:00
2013-05-03 10:37:59 -07:00
import devicemanager
import droid
2011-12-31 07:03:36 -08:00
import manifestparser
2013-10-08 12:14:38 -07:00
import mozinfo
2014-04-21 08:03:51 -07:00
import moznetwork
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
class RemoteOptions ( MochitestOptions ) :
2013-07-26 11:40:04 -07:00
def __init__ ( self , automation , * * kwargs ) :
2010-02-25 11:10:39 -08:00
defaults = { }
2013-09-23 07:47:48 -07:00
self . _automation = automation or Automation ( )
MochitestOptions . __init__ ( self )
2010-02-25 11:10:39 -08:00
2010-06-24 02:32:01 -07:00
self . add_option ( " --remote-app-path " , action = " store " ,
type = " string " , dest = " remoteAppPath " ,
help = " Path to remote executable relative to device root using only forward slashes. Either this or app must be specified but not both " )
defaults [ " remoteAppPath " ] = None
2010-02-25 11:10:39 -08:00
self . add_option ( " --deviceIP " , action = " store " ,
type = " string " , dest = " deviceIP " ,
help = " ip address of remote device to test " )
defaults [ " deviceIP " ] = None
2011-05-06 15:17:55 -07:00
self . add_option ( " --dm_trans " , action = " store " ,
type = " string " , dest = " dm_trans " ,
help = " the transport to use to communicate with device: [adb|sut]; default=sut " )
defaults [ " dm_trans " ] = " sut "
2010-02-25 11:10:39 -08:00
self . add_option ( " --devicePort " , action = " store " ,
type = " string " , dest = " devicePort " ,
help = " port of remote device to test " )
2010-05-27 13:02:15 -07:00
defaults [ " devicePort " ] = 20701
2010-02-25 11:10:39 -08:00
2010-06-24 02:32:01 -07:00
self . add_option ( " --remote-product-name " , action = " store " ,
2010-02-25 11:10:39 -08:00
type = " string " , dest = " remoteProductName " ,
2010-05-27 13:02:15 -07:00
help = " The executable ' s name of remote product to test - either fennec or firefox, defaults to fennec " )
defaults [ " remoteProductName " ] = " fennec "
2010-02-25 11:10:39 -08:00
self . add_option ( " --remote-logfile " , action = " store " ,
type = " string " , dest = " remoteLogFile " ,
2010-05-27 13:02:15 -07:00
help = " Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME. " )
2010-02-25 11:10:39 -08:00
defaults [ " remoteLogFile " ] = None
2010-03-13 10:34:19 -08:00
self . add_option ( " --remote-webserver " , action = " store " ,
type = " string " , dest = " remoteWebServer " ,
help = " ip address where the remote web server is hosted at " )
defaults [ " remoteWebServer " ] = None
self . add_option ( " --http-port " , action = " store " ,
type = " string " , dest = " httpPort " ,
2012-06-05 14:07:14 -07:00
help = " http port of the remote web server " )
2010-03-13 10:34:19 -08:00
defaults [ " httpPort " ] = automation . DEFAULT_HTTP_PORT
self . add_option ( " --ssl-port " , action = " store " ,
type = " string " , dest = " sslPort " ,
2012-06-05 14:07:14 -07:00
help = " ssl port of the remote web server " )
2010-03-13 10:34:19 -08:00
defaults [ " sslPort " ] = automation . DEFAULT_SSL_PORT
2010-02-25 11:10:39 -08:00
2013-05-20 11:39:50 -07:00
self . add_option ( " --robocop-ini " , action = " store " ,
type = " string " , dest = " robocopIni " ,
help = " name of the .ini file containing the list of tests to run " )
defaults [ " robocopIni " ] = " "
2011-12-31 07:03:36 -08:00
self . add_option ( " --robocop " , action = " store " ,
type = " string " , dest = " robocop " ,
2013-05-20 11:39:50 -07:00
help = " name of the .ini file containing the list of tests to run. [DEPRECATED- please use --robocop-ini " )
2011-12-31 07:03:36 -08:00
defaults [ " robocop " ] = " "
2013-05-20 11:39:50 -07:00
self . add_option ( " --robocop-apk " , action = " store " ,
type = " string " , dest = " robocopApk " ,
help = " name of the Robocop APK to use for ADB test running " )
defaults [ " robocopApk " ] = " "
2012-01-07 15:41:08 -08:00
self . add_option ( " --robocop-path " , action = " store " ,
type = " string " , dest = " robocopPath " ,
2013-05-20 11:39:50 -07:00
help = " Path to the folder where robocop.apk is located at. Primarily used for ADB test running. [DEPRECATED- please use --robocop-apk] " )
2012-01-07 15:41:08 -08:00
defaults [ " robocopPath " ] = " "
2012-01-30 10:14:47 -08:00
self . add_option ( " --robocop-ids " , action = " store " ,
type = " string " , dest = " robocopIds " ,
help = " name of the file containing the view ID map (fennec_ids.txt) " )
defaults [ " robocopIds " ] = " "
2012-12-20 08:11:11 -08:00
self . add_option ( " --remoteTestRoot " , action = " store " ,
type = " string " , dest = " remoteTestRoot " ,
help = " remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests) " )
2010-05-27 13:02:15 -07:00
defaults [ " remoteTestRoot " ] = None
2012-12-20 08:11:11 -08:00
2010-02-25 11:10:39 -08:00
defaults [ " logFile " ] = " mochitest.log "
defaults [ " autorun " ] = True
defaults [ " closeWhenDone " ] = True
defaults [ " testPath " ] = " "
2010-05-27 13:02:15 -07:00
defaults [ " app " ] = None
2013-09-12 08:02:48 -07:00
defaults [ " utilityPath " ] = None
2010-02-25 11:10:39 -08:00
self . set_defaults ( * * defaults )
2010-05-27 13:02:15 -07:00
def verifyRemoteOptions ( self , options , automation ) :
2014-08-13 09:03:00 -07:00
options_logger = logging . getLogger ( ' MochitestRemote ' )
2012-12-20 08:11:11 -08:00
if not options . remoteTestRoot :
2014-07-11 12:29:30 -07:00
options . remoteTestRoot = automation . _devicemanager . deviceRoot
2010-03-13 10:34:19 -08:00
2010-12-09 14:47:21 -08:00
if options . remoteWebServer == None :
if os . name != " nt " :
2014-04-21 08:03:51 -07:00
options . remoteWebServer = moznetwork . get_ip ( )
2010-12-09 14:47:21 -08:00
else :
2014-08-13 09:03:00 -07:00
options_logger . error ( " you must specify a --remote-webserver=<ip address> " )
2010-12-09 14:47:21 -08:00
return None
2010-05-27 13:02:15 -07:00
options . webServer = options . remoteWebServer
2010-02-25 11:10:39 -08:00
if ( options . deviceIP == None ) :
2014-08-13 09:03:00 -07:00
options_logger . error ( " you must provide a device IP " )
2010-06-24 02:32:01 -07:00
return None
2010-02-25 11:10:39 -08:00
if ( options . remoteLogFile == None ) :
2011-07-07 10:10:52 -07:00
options . remoteLogFile = options . remoteTestRoot + ' /logs/mochitest.log '
2010-09-29 16:20:33 -07:00
if ( options . remoteLogFile . count ( ' / ' ) < 1 ) :
2010-12-09 14:47:21 -08:00
options . remoteLogFile = options . remoteTestRoot + ' / ' + options . remoteLogFile
2010-06-15 13:02:17 -07:00
2010-06-24 02:32:01 -07:00
# remoteAppPath or app must be specified to find the product to launch
if ( options . remoteAppPath and options . app ) :
2014-08-13 09:03:00 -07:00
options_logger . error ( " You cannot specify both the remoteAppPath and the app setting " )
2010-06-24 02:32:01 -07:00
return None
elif ( options . remoteAppPath ) :
options . app = options . remoteTestRoot + " / " + options . remoteAppPath
elif ( options . app == None ) :
# Neither remoteAppPath nor app are set -- error
2014-08-13 09:03:00 -07:00
options_logger . error ( " You must specify either appPath or app " )
2010-06-24 02:32:01 -07:00
return None
2010-05-27 13:02:15 -07:00
# Only reset the xrePath if it wasn't provided
if ( options . xrePath == None ) :
2013-09-12 08:02:48 -07:00
options . xrePath = options . utilityPath
2010-05-27 13:02:15 -07:00
2011-04-19 15:17:01 -07:00
if ( options . pidFile != " " ) :
f = open ( options . pidFile , ' w ' )
f . write ( " %s " % os . getpid ( ) )
f . close ( )
2013-05-20 11:39:50 -07:00
# Robocop specific deprecated options.
if options . robocop :
if options . robocopIni :
2014-08-13 09:03:00 -07:00
options_logger . error ( " can not use deprecated --robocop and replacement --robocop-ini together " )
2013-05-20 11:39:50 -07:00
return None
options . robocopIni = options . robocop
del options . robocop
if options . robocopPath :
if options . robocopApk :
2014-08-13 09:03:00 -07:00
options_logger . error ( " can not use deprecated --robocop-path and replacement --robocop-apk together " )
2013-05-20 11:39:50 -07:00
return None
options . robocopApk = os . path . join ( options . robocopPath , ' robocop.apk ' )
del options . robocopPath
2012-01-07 15:41:08 -08:00
# Robocop specific options
2013-05-20 11:39:50 -07:00
if options . robocopIni != " " :
if not os . path . exists ( options . robocopIni ) :
2014-08-13 09:03:00 -07:00
options_logger . error ( " Unable to find specified robocop .ini manifest ' %s ' " % options . robocopIni )
2012-01-07 15:41:08 -08:00
return None
2013-05-20 11:39:50 -07:00
options . robocopIni = os . path . abspath ( options . robocopIni )
2012-01-07 15:41:08 -08:00
2013-05-20 11:39:50 -07:00
if options . robocopApk != " " :
if not os . path . exists ( options . robocopApk ) :
2014-08-13 09:03:00 -07:00
options_logger . error ( " Unable to find robocop APK ' %s ' " % options . robocopApk )
2012-01-07 15:41:08 -08:00
return None
2013-05-20 11:39:50 -07:00
options . robocopApk = os . path . abspath ( options . robocopApk )
2012-01-07 15:41:08 -08:00
2012-01-30 10:14:47 -08:00
if options . robocopIds != " " :
if not os . path . exists ( options . robocopIds ) :
2014-08-13 09:03:00 -07:00
options_logger . error ( " Unable to find specified robocop IDs file ' %s ' " % options . robocopIds )
2012-01-30 10:14:47 -08:00
return None
options . robocopIds = os . path . abspath ( options . robocopIds )
2012-12-28 04:18:22 -08:00
# allow us to keep original application around for cleanup while running robocop via 'am'
options . remoteappname = options . app
2010-05-27 13:02:15 -07:00
return options
def verifyOptions ( self , options , mochitest ) :
# since we are reusing verifyOptions, it will exit if App is not found
temp = options . app
2013-08-26 14:17:51 -07:00
options . app = __file__
2010-05-27 13:02:15 -07:00
tempPort = options . httpPort
tempSSL = options . sslPort
tempIP = options . webServer
2013-11-21 08:33:43 -08:00
# We are going to override this option later anyway, just pretend
# like it's not set for verification purposes.
options . dumpOutputDirectory = None
2010-05-27 13:02:15 -07:00
options = MochitestOptions . verifyOptions ( self , options , mochitest )
options . webServer = tempIP
options . app = temp
options . sslPort = tempSSL
options . httpPort = tempPort
2010-02-25 11:10:39 -08:00
2014-03-14 11:25:41 -07:00
return options
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 " )
self . _dm . removeDir ( self . remoteNSPR ) ;
self . _dm . mkDir ( self . remoteNSPR ) ;
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 :
2014-08-13 09:03:00 -07: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 )
2014-08-13 15:23:26 -07:00
self . _dm . getDirectory ( self . remoteNSPR , os . environ [ " MOZ_UPLOAD_DIR " ] )
2014-06-03 08:19:28 -07:00
Mochitest . cleanup ( self , options )
2010-02-25 11:10:39 -08:00
2010-05-27 13:02:15 -07: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
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 )
if options . xrePath == None :
2014-08-13 09:03:00 -07:00
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
2010-06-24 02:32:01 -07:00
if options . utilityPath == None :
2014-08-13 09:03:00 -07:00
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 '
2013-09-05 09:14:56 -07:00
' the --utility-path argument to specify the path '
' to a desktop version. ' % xpcshell_path )
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 )
Mochitest . startServers ( self , options , debuggerInfo )
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 ' ) )
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 ' ) )
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 :
2014-08-13 09:03:00 -07: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 :
2012-12-28 04:18:22 -08:00
#we really need testConfig.js (for browser chrome)
try :
self . _dm . pushDir ( options . profilePath , self . remoteProfile )
except devicemanager . DMError :
2014-08-13 09:03:00 -07: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 :
2014-07-04 04:55:00 -07:00
return super ( MochiRemote , self ) . buildTestPath ( options , testsToFilter )
2014-03-18 08:03:51 -07:00
2010-02-25 11:10:39 -08:00
def installChromeFile ( self , filename , options ) :
2010-05-27 13:02:15 -07:00
parts = options . app . split ( ' / ' )
if ( parts [ 0 ] == options . app ) :
return " NO_CHROME_ON_DROID "
path = ' / ' . join ( parts [ : - 1 ] )
2010-03-15 15:47:34 -07:00
manifest = path + " /chrome/ " + os . path . basename ( filename )
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 . pushFile ( filename , manifest )
except devicemanager . DMError :
2014-08-13 09:03:00 -07:00
self . log . error ( " Automation Error: Unable to install Chrome files on 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-02-25 11:10:39 -08:00
return manifest
2014-03-14 11:25:41 -07:00
def getLogFilePath ( self , logFile ) :
2010-02-25 11:10:39 -08:00
return logFile
2012-02-09 05:49:00 -08:00
# In the future we could use LogParser: http://hg.mozilla.org/automation/logparser/
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 )
if not isinstance ( message , dict ) or not ' action ' in message :
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 :
2014-08-13 09:03:00 -07:00
self . log . error ( " 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 )
# TODO: Consider not printing to stdout because we might be duplicating output
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 ) :
2014-08-13 09:03:00 -07: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 :
logcat = self . _dm . getLogcat ( filterOutRegexps = fennecLogcatFilters )
2014-08-13 09:03:00 -07:00
self . log . info ( ' \n ' + ' ' . join ( logcat ) . decode ( ' utf-8 ' , ' replace ' ) )
self . log . info ( " Device info: %s " % self . _dm . getInfo ( ) )
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 " )
fHandle . write ( " rawhost=http:// %s : %s /tests \n " % ( options . remoteWebServer , options . httpPort ) )
if browserEnv :
envstr = " "
delim = " "
for key , value in browserEnv . items ( ) :
try :
value . index ( ' , ' )
2014-08-13 09:03:00 -07:00
self . log . error ( " buildRobotiumConfig: browserEnv - Found a ' , ' in our value, unable to process value. key= %s ,value= %s " % ( key , value ) )
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 " ) )
self . _dm . pushFile ( fHandle . name , os . path . join ( deviceRoot , " robotium.config " ) )
os . unlink ( fHandle . name )
2014-07-25 04:01:13 -07:00
def getGMPPluginPath ( self , options ) :
# TODO: bug 1043403
return None
2013-09-16 11:44:25 -07:00
def buildBrowserEnv ( self , options , debugger = False ) :
browserEnv = Mochitest . buildBrowserEnv ( self , options , debugger = debugger )
2014-08-13 15:23:26 -07:00
# override nsprLogs to avoid processing in Mochitest base class
self . nsprLogs = None
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 )
2010-02-25 11:10:39 -08:00
def main ( ) :
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
2013-07-26 11:40:04 -07:00
parser = RemoteOptions ( auto )
2014-08-13 09:03:00 -07:00
structured . commandline . add_logging_group ( parser )
2010-02-25 11:10:39 -08:00
options , args = parser . parse_args ( )
2013-05-20 11:39:50 -07:00
2012-01-07 15:41:08 -08:00
if ( options . dm_trans == " adb " ) :
2011-05-06 15:17:55 -07:00
if ( options . deviceIP ) :
2013-05-03 10:37:59 -07:00
dm = droid . DroidADB ( options . deviceIP , options . devicePort , deviceRoot = options . remoteTestRoot )
2011-05-06 15:17:55 -07:00
else :
2013-05-03 10:37:59 -07:00
dm = droid . DroidADB ( deviceRoot = options . remoteTestRoot )
2011-05-06 15:17:55 -07:00
else :
2013-05-03 10:37:59 -07:00
dm = droid . DroidSUT ( options . deviceIP , options . devicePort , deviceRoot = options . remoteTestRoot )
2010-02-25 11:10:39 -08:00
auto . setDeviceManager ( dm )
2010-05-27 13:02:15 -07:00
options = parser . verifyRemoteOptions ( options , auto )
2014-08-13 09:03:00 -07:00
mochitest = MochiRemote ( auto , dm , options )
log = mochitest . log
structured_logger = mochitest . structured_logger
message_logger . logger = mochitest . structured_logger
mochitest . message_logger = message_logger
2010-05-27 13:02:15 -07:00
if ( options == None ) :
2013-09-05 09:14:54 -07:00
log . error ( " Invalid options specified, use --help for a list of valid options " )
2010-06-24 02:32:01 -07:00
sys . exit ( 1 )
2010-02-25 11:10:39 -08:00
productPieces = options . remoteProductName . split ( ' . ' )
if ( productPieces != 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
options = parser . verifyOptions ( options , mochitest )
if ( options == None ) :
2010-06-24 02:32:01 -07:00
sys . exit ( 1 )
2014-03-14 11:25:41 -07:00
2011-07-07 10:10:52 -07:00
logParent = os . path . dirname ( options . remoteLogFile )
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 ' ] )
log . info ( " Android sdk version ' %s ' ; will use this to filter manifests " % str ( androidVersion ) )
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
2012-01-07 15:41:08 -08:00
mp = manifestparser . TestManifest ( strict = False )
# TODO: pull this in dynamically
2013-05-20 11:39:50 -07:00
mp . read ( options . robocopIni )
2013-10-08 12:14:38 -07:00
robocop_tests = mp . active_tests ( exists = False , * * mozinfo . info )
2013-02-21 06:03:02 -08:00
tests = [ ]
my_tests = tests
for test in robocop_tests :
tests . append ( test [ ' name ' ] )
if options . totalChunks :
tests_per_chunk = math . ceil ( len ( tests ) / ( options . totalChunks * 1.0 ) )
start = int ( round ( ( options . thisChunk - 1 ) * tests_per_chunk ) )
end = int ( round ( options . thisChunk * tests_per_chunk ) )
if end > len ( tests ) :
end = len ( tests )
my_tests = tests [ start : end ]
2014-07-17 00:02:00 -07:00
log . info ( " Running tests %d - %d / %d " % ( start + 1 , end , len ( tests ) ) )
2012-01-07 15:41:08 -08:00
2012-09-12 04:56:31 -07:00
dm . removeFile ( os . path . join ( deviceRoot , " fennec_ids.txt " ) )
2014-04-16 07:29:39 -07:00
fennec_ids = os . path . abspath ( os . path . join ( SCRIPT_DIR , " fennec_ids.txt " ) )
2012-01-30 10:14:47 -08:00
if not os . path . exists ( fennec_ids ) and options . robocopIds :
fennec_ids = options . robocopIds
2012-09-12 04:56:31 -07:00
dm . pushFile ( fennec_ids , os . path . join ( deviceRoot , " fennec_ids.txt " ) )
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-02-21 06:03:02 -08:00
if not test [ ' name ' ] in my_tests :
continue
2013-10-08 12:14:39 -07:00
if ' disabled ' in test :
log . info ( ' TEST-INFO | skipping %s | %s ' % ( test [ ' name ' ] , test [ ' disabled ' ] ) )
continue
2014-08-06 10:55:00 -07:00
active_tests . append ( test )
2014-08-13 09:03:00 -07:00
structured_logger . suite_start ( [ t [ ' name ' ] for t in active_tests ] )
2014-08-06 10:55:00 -07:00
for test in active_tests :
2013-07-30 05:30:40 -07:00
# When running in a loop, we need to create a fresh profile for each cycle
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 "
2012-09-12 04:56:31 -07:00
options . browserArgs = [ " instrument " , " -w " , " -e " , " deviceroot " , deviceRoot , " -e " , " class " ]
2013-11-07 08:18:51 -08:00
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
2013-03-18 02:15:17 -07:00
# If the test is for checking the import from bookmarks then make sure there is data to import
if test [ ' name ' ] == " testImportFromAndroid " :
2014-03-14 11:25:41 -07:00
2013-03-18 02:15:17 -07:00
# Get the OS so we can run the insert in the apropriate database and following the correct table schema
osInfo = dm . getInfo ( " os " )
devOS = " " . join ( osInfo [ ' os ' ] )
if ( " pandaboard " in devOS ) :
delete = [ ' execsu ' , ' sqlite3 ' , " /data/data/com.android.browser/databases/browser2.db \' delete from bookmarks where _id > 14; \' " ]
else :
delete = [ ' execsu ' , ' sqlite3 ' , " /data/data/com.android.browser/databases/browser.db \' delete from bookmarks where _id > 14; \' " ]
if ( options . dm_trans == " sut " ) :
dm . _runCmds ( [ { " cmd " : " " . join ( delete ) } ] )
# Insert the bookmarks
2013-09-05 09:14:54 -07:00
log . info ( " Insert bookmarks in the default android browser database " )
2013-03-18 02:15:17 -07:00
for i in range ( 20 ) :
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 )
2012-11-20 07:24:28 -08:00
# Ensure earlier failures aren't overwritten by success on this run
if retVal is None or retVal == 0 :
retVal = result
2012-01-07 15:41:08 -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-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 ) :
cmd_del = [ ' execsu ' , ' sqlite3 ' , " /data/data/com.android.browser/databases/browser2.db \' delete from bookmarks where _id > 14; \' " ]
else :
cmd_del = [ ' execsu ' , ' sqlite3 ' , " /data/data/com.android.browser/databases/browser.db \' delete from bookmarks where _id > 14; \' " ]
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-07-29 05:11:00 -07:00
message_logger . finish ( )
2013-06-24 17:15:40 -07:00
mochitest . printDeviceInfo ( printLogcat = True )
2012-01-07 15:41:08 -08:00
2011-09-26 04:41:19 -07:00
sys . exit ( retVal )
2012-12-04 07:54:37 -08:00
2010-02-25 11:10:39 -08:00
if __name__ == " __main__ " :
2010-06-24 02:32:01 -07:00
main ( )