layout/tools/reftest/remotereftest.py

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 # This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 # License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
michael@0 4
michael@0 5 import sys
michael@0 6 import os
michael@0 7 import time
michael@0 8 import tempfile
michael@0 9 import traceback
michael@0 10
michael@0 11 # We need to know our current directory so that we can serve our test files from it.
michael@0 12 SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
michael@0 13
michael@0 14 from runreftest import RefTest
michael@0 15 from runreftest import ReftestOptions
michael@0 16 from automation import Automation
michael@0 17 import devicemanager
michael@0 18 import droid
michael@0 19 import moznetwork
michael@0 20 from remoteautomation import RemoteAutomation, fennecLogcatFilters
michael@0 21
michael@0 22 class RemoteOptions(ReftestOptions):
michael@0 23 def __init__(self, automation):
michael@0 24 ReftestOptions.__init__(self, automation)
michael@0 25
michael@0 26 defaults = {}
michael@0 27 defaults["logFile"] = "reftest.log"
michael@0 28 # app, xrePath and utilityPath variables are set in main function
michael@0 29 defaults["app"] = ""
michael@0 30 defaults["xrePath"] = ""
michael@0 31 defaults["utilityPath"] = ""
michael@0 32 defaults["runTestsInParallel"] = False
michael@0 33
michael@0 34 self.add_option("--remote-app-path", action="store",
michael@0 35 type = "string", dest = "remoteAppPath",
michael@0 36 help = "Path to remote executable relative to device root using only forward slashes. Either this or app must be specified, but not both.")
michael@0 37 defaults["remoteAppPath"] = None
michael@0 38
michael@0 39 self.add_option("--deviceIP", action="store",
michael@0 40 type = "string", dest = "deviceIP",
michael@0 41 help = "ip address of remote device to test")
michael@0 42 defaults["deviceIP"] = None
michael@0 43
michael@0 44 self.add_option("--devicePort", action="store",
michael@0 45 type = "string", dest = "devicePort",
michael@0 46 help = "port of remote device to test")
michael@0 47 defaults["devicePort"] = 20701
michael@0 48
michael@0 49 self.add_option("--remote-product-name", action="store",
michael@0 50 type = "string", dest = "remoteProductName",
michael@0 51 help = "Name of product to test - either fennec or firefox, defaults to fennec")
michael@0 52 defaults["remoteProductName"] = "fennec"
michael@0 53
michael@0 54 self.add_option("--remote-webserver", action="store",
michael@0 55 type = "string", dest = "remoteWebServer",
michael@0 56 help = "IP Address of the webserver hosting the reftest content")
michael@0 57 defaults["remoteWebServer"] = moznetwork.get_ip()
michael@0 58
michael@0 59 self.add_option("--http-port", action = "store",
michael@0 60 type = "string", dest = "httpPort",
michael@0 61 help = "port of the web server for http traffic")
michael@0 62 defaults["httpPort"] = automation.DEFAULT_HTTP_PORT
michael@0 63
michael@0 64 self.add_option("--ssl-port", action = "store",
michael@0 65 type = "string", dest = "sslPort",
michael@0 66 help = "Port for https traffic to the web server")
michael@0 67 defaults["sslPort"] = automation.DEFAULT_SSL_PORT
michael@0 68
michael@0 69 self.add_option("--remote-logfile", action="store",
michael@0 70 type = "string", dest = "remoteLogFile",
michael@0 71 help = "Name of log file on the device relative to device root. PLEASE USE ONLY A FILENAME.")
michael@0 72 defaults["remoteLogFile"] = None
michael@0 73
michael@0 74 self.add_option("--enable-privilege", action="store_true", dest = "enablePrivilege",
michael@0 75 help = "add webserver and port to the user.js file for remote script access and universalXPConnect")
michael@0 76 defaults["enablePrivilege"] = False
michael@0 77
michael@0 78 self.add_option("--pidfile", action = "store",
michael@0 79 type = "string", dest = "pidFile",
michael@0 80 help = "name of the pidfile to generate")
michael@0 81 defaults["pidFile"] = ""
michael@0 82
michael@0 83 self.add_option("--bootstrap", action="store_true", dest = "bootstrap",
michael@0 84 help = "test with a bootstrap addon required for native Fennec")
michael@0 85 defaults["bootstrap"] = False
michael@0 86
michael@0 87 self.add_option("--dm_trans", action="store",
michael@0 88 type = "string", dest = "dm_trans",
michael@0 89 help = "the transport to use to communicate with device: [adb|sut]; default=sut")
michael@0 90 defaults["dm_trans"] = "sut"
michael@0 91
michael@0 92 self.add_option("--remoteTestRoot", action = "store",
michael@0 93 type = "string", dest = "remoteTestRoot",
michael@0 94 help = "remote directory to use as test root (eg. /mnt/sdcard/tests or /data/local/tests)")
michael@0 95 defaults["remoteTestRoot"] = None
michael@0 96
michael@0 97 self.add_option("--httpd-path", action = "store",
michael@0 98 type = "string", dest = "httpdPath",
michael@0 99 help = "path to the httpd.js file")
michael@0 100 defaults["httpdPath"] = None
michael@0 101
michael@0 102 defaults["localLogName"] = None
michael@0 103
michael@0 104 self.set_defaults(**defaults)
michael@0 105
michael@0 106 def verifyRemoteOptions(self, options):
michael@0 107 if options.runTestsInParallel:
michael@0 108 self.error("Cannot run parallel tests here")
michael@0 109
michael@0 110 # Ensure our defaults are set properly for everything we can infer
michael@0 111 if not options.remoteTestRoot:
michael@0 112 options.remoteTestRoot = self.automation._devicemanager.getDeviceRoot() + '/reftest'
michael@0 113 options.remoteProfile = options.remoteTestRoot + "/profile"
michael@0 114
michael@0 115 # Verify that our remotewebserver is set properly
michael@0 116 if (options.remoteWebServer == None or
michael@0 117 options.remoteWebServer == '127.0.0.1'):
michael@0 118 print "ERROR: Either you specified the loopback for the remote webserver or ",
michael@0 119 print "your local IP cannot be detected. Please provide the local ip in --remote-webserver"
michael@0 120 return None
michael@0 121
michael@0 122 # One of remoteAppPath (relative path to application) or the app (executable) must be
michael@0 123 # set, but not both. If both are set, we destroy the user's selection for app
michael@0 124 # so instead of silently destroying a user specificied setting, we error.
michael@0 125 if (options.remoteAppPath and options.app):
michael@0 126 print "ERROR: You cannot specify both the remoteAppPath and the app"
michael@0 127 return None
michael@0 128 elif (options.remoteAppPath):
michael@0 129 options.app = options.remoteTestRoot + "/" + options.remoteAppPath
michael@0 130 elif (options.app == None):
michael@0 131 # Neither remoteAppPath nor app are set -- error
michael@0 132 print "ERROR: You must specify either appPath or app"
michael@0 133 return None
michael@0 134
michael@0 135 if (options.xrePath == None):
michael@0 136 print "ERROR: You must specify the path to the controller xre directory"
michael@0 137 return None
michael@0 138 else:
michael@0 139 # Ensure xrepath is a full path
michael@0 140 options.xrePath = os.path.abspath(options.xrePath)
michael@0 141
michael@0 142 # Default to <deviceroot>/reftest/reftest.log
michael@0 143 if (options.remoteLogFile == None):
michael@0 144 options.remoteLogFile = 'reftest.log'
michael@0 145
michael@0 146 options.localLogName = options.remoteLogFile
michael@0 147 options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile
michael@0 148
michael@0 149 # Ensure that the options.logfile (which the base class uses) is set to
michael@0 150 # the remote setting when running remote. Also, if the user set the
michael@0 151 # log file name there, use that instead of reusing the remotelogfile as above.
michael@0 152 if (options.logFile):
michael@0 153 # If the user specified a local logfile name use that
michael@0 154 options.localLogName = options.logFile
michael@0 155
michael@0 156 options.logFile = options.remoteLogFile
michael@0 157
michael@0 158 if (options.pidFile != ""):
michael@0 159 f = open(options.pidFile, 'w')
michael@0 160 f.write("%s" % os.getpid())
michael@0 161 f.close()
michael@0 162
michael@0 163 # httpd-path is specified by standard makefile targets and may be specified
michael@0 164 # on the command line to select a particular version of httpd.js. If not
michael@0 165 # specified, try to select the one from hostutils.zip, as required in bug 882932.
michael@0 166 if not options.httpdPath:
michael@0 167 options.httpdPath = os.path.join(options.utilityPath, "components")
michael@0 168
michael@0 169 # TODO: Copied from main, but I think these are no longer used in a post xulrunner world
michael@0 170 #options.xrePath = options.remoteTestRoot + self.automation._product + '/xulrunner'
michael@0 171 #options.utilityPath = options.testRoot + self.automation._product + '/bin'
michael@0 172 return options
michael@0 173
michael@0 174 class ReftestServer:
michael@0 175 """ Web server used to serve Reftests, for closer fidelity to the real web.
michael@0 176 It is virtually identical to the server used in mochitest and will only
michael@0 177 be used for running reftests remotely.
michael@0 178 Bug 581257 has been filed to refactor this wrapper around httpd.js into
michael@0 179 it's own class and use it in both remote and non-remote testing. """
michael@0 180
michael@0 181 def __init__(self, automation, options, scriptDir):
michael@0 182 self.automation = automation
michael@0 183 self._utilityPath = options.utilityPath
michael@0 184 self._xrePath = options.xrePath
michael@0 185 self._profileDir = options.serverProfilePath
michael@0 186 self.webServer = options.remoteWebServer
michael@0 187 self.httpPort = options.httpPort
michael@0 188 self.scriptDir = scriptDir
michael@0 189 self.pidFile = options.pidFile
michael@0 190 self._httpdPath = os.path.abspath(options.httpdPath)
michael@0 191 self.shutdownURL = "http://%(server)s:%(port)s/server/shutdown" % { "server" : self.webServer, "port" : self.httpPort }
michael@0 192
michael@0 193 def start(self):
michael@0 194 "Run the Refest server, returning the process ID of the server."
michael@0 195
michael@0 196 env = self.automation.environment(xrePath = self._xrePath)
michael@0 197 env["XPCOM_DEBUG_BREAK"] = "warn"
michael@0 198 if self.automation.IS_WIN32:
michael@0 199 env["PATH"] = env["PATH"] + ";" + self._xrePath
michael@0 200
michael@0 201 args = ["-g", self._xrePath,
michael@0 202 "-v", "170",
michael@0 203 "-f", os.path.join(self._httpdPath, "httpd.js"),
michael@0 204 "-e", "const _PROFILE_PATH = '%(profile)s';const _SERVER_PORT = '%(port)s'; const _SERVER_ADDR ='%(server)s';" %
michael@0 205 {"profile" : self._profileDir.replace('\\', '\\\\'), "port" : self.httpPort, "server" : self.webServer },
michael@0 206 "-f", os.path.join(self.scriptDir, "server.js")]
michael@0 207
michael@0 208 xpcshell = os.path.join(self._utilityPath,
michael@0 209 "xpcshell" + self.automation.BIN_SUFFIX)
michael@0 210
michael@0 211 if not os.access(xpcshell, os.F_OK):
michael@0 212 raise Exception('xpcshell not found at %s' % xpcshell)
michael@0 213 if self.automation.elf_arm(xpcshell):
michael@0 214 raise Exception('xpcshell at %s is an ARM binary; please use '
michael@0 215 'the --utility-path argument to specify the path '
michael@0 216 'to a desktop version.' % xpcshell)
michael@0 217
michael@0 218 self._process = self.automation.Process([xpcshell] + args, env = env)
michael@0 219 pid = self._process.pid
michael@0 220 if pid < 0:
michael@0 221 print "TEST-UNEXPECTED-FAIL | remotereftests.py | Error starting server."
michael@0 222 return 2
michael@0 223 self.automation.log.info("INFO | remotereftests.py | Server pid: %d", pid)
michael@0 224
michael@0 225 if (self.pidFile != ""):
michael@0 226 f = open(self.pidFile + ".xpcshell.pid", 'w')
michael@0 227 f.write("%s" % pid)
michael@0 228 f.close()
michael@0 229
michael@0 230 def ensureReady(self, timeout):
michael@0 231 assert timeout >= 0
michael@0 232
michael@0 233 aliveFile = os.path.join(self._profileDir, "server_alive.txt")
michael@0 234 i = 0
michael@0 235 while i < timeout:
michael@0 236 if os.path.exists(aliveFile):
michael@0 237 break
michael@0 238 time.sleep(1)
michael@0 239 i += 1
michael@0 240 else:
michael@0 241 print "TEST-UNEXPECTED-FAIL | remotereftests.py | Timed out while waiting for server startup."
michael@0 242 self.stop()
michael@0 243 return 1
michael@0 244
michael@0 245 def stop(self):
michael@0 246 if hasattr(self, '_process'):
michael@0 247 try:
michael@0 248 c = urllib2.urlopen(self.shutdownURL)
michael@0 249 c.read()
michael@0 250 c.close()
michael@0 251
michael@0 252 rtncode = self._process.poll()
michael@0 253 if (rtncode == None):
michael@0 254 self._process.terminate()
michael@0 255 except:
michael@0 256 self._process.kill()
michael@0 257
michael@0 258 class RemoteReftest(RefTest):
michael@0 259 remoteApp = ''
michael@0 260
michael@0 261 def __init__(self, automation, devicemanager, options, scriptDir):
michael@0 262 RefTest.__init__(self, automation)
michael@0 263 self._devicemanager = devicemanager
michael@0 264 self.scriptDir = scriptDir
michael@0 265 self.remoteApp = options.app
michael@0 266 self.remoteProfile = options.remoteProfile
michael@0 267 self.remoteTestRoot = options.remoteTestRoot
michael@0 268 self.remoteLogFile = options.remoteLogFile
michael@0 269 self.localLogName = options.localLogName
michael@0 270 self.pidFile = options.pidFile
michael@0 271 if self.automation.IS_DEBUG_BUILD:
michael@0 272 self.SERVER_STARTUP_TIMEOUT = 180
michael@0 273 else:
michael@0 274 self.SERVER_STARTUP_TIMEOUT = 90
michael@0 275 self.automation.deleteANRs()
michael@0 276
michael@0 277 def findPath(self, paths, filename = None):
michael@0 278 for path in paths:
michael@0 279 p = path
michael@0 280 if filename:
michael@0 281 p = os.path.join(p, filename)
michael@0 282 if os.path.exists(self.getFullPath(p)):
michael@0 283 return path
michael@0 284 return None
michael@0 285
michael@0 286 def startWebServer(self, options):
michael@0 287 """ Create the webserver on the host and start it up """
michael@0 288 remoteXrePath = options.xrePath
michael@0 289 remoteUtilityPath = options.utilityPath
michael@0 290 localAutomation = Automation()
michael@0 291 localAutomation.IS_WIN32 = False
michael@0 292 localAutomation.IS_LINUX = False
michael@0 293 localAutomation.IS_MAC = False
michael@0 294 localAutomation.UNIXISH = False
michael@0 295 hostos = sys.platform
michael@0 296 if (hostos == 'mac' or hostos == 'darwin'):
michael@0 297 localAutomation.IS_MAC = True
michael@0 298 elif (hostos == 'linux' or hostos == 'linux2'):
michael@0 299 localAutomation.IS_LINUX = True
michael@0 300 localAutomation.UNIXISH = True
michael@0 301 elif (hostos == 'win32' or hostos == 'win64'):
michael@0 302 localAutomation.BIN_SUFFIX = ".exe"
michael@0 303 localAutomation.IS_WIN32 = True
michael@0 304
michael@0 305 paths = [options.xrePath, localAutomation.DIST_BIN, self.automation._product, os.path.join('..', self.automation._product)]
michael@0 306 options.xrePath = self.findPath(paths)
michael@0 307 if options.xrePath == None:
michael@0 308 print "ERROR: unable to find xulrunner path for %s, please specify with --xre-path" % (os.name)
michael@0 309 return 1
michael@0 310 paths.append("bin")
michael@0 311 paths.append(os.path.join("..", "bin"))
michael@0 312
michael@0 313 xpcshell = "xpcshell"
michael@0 314 if (os.name == "nt"):
michael@0 315 xpcshell += ".exe"
michael@0 316
michael@0 317 if (options.utilityPath):
michael@0 318 paths.insert(0, options.utilityPath)
michael@0 319 options.utilityPath = self.findPath(paths, xpcshell)
michael@0 320 if options.utilityPath == None:
michael@0 321 print "ERROR: unable to find utility path for %s, please specify with --utility-path" % (os.name)
michael@0 322 return 1
michael@0 323
michael@0 324 options.serverProfilePath = tempfile.mkdtemp()
michael@0 325 self.server = ReftestServer(localAutomation, options, self.scriptDir)
michael@0 326 retVal = self.server.start()
michael@0 327 if retVal:
michael@0 328 return retVal
michael@0 329 retVal = self.server.ensureReady(self.SERVER_STARTUP_TIMEOUT)
michael@0 330 if retVal:
michael@0 331 return retVal
michael@0 332
michael@0 333 options.xrePath = remoteXrePath
michael@0 334 options.utilityPath = remoteUtilityPath
michael@0 335 return 0
michael@0 336
michael@0 337 def stopWebServer(self, options):
michael@0 338 self.server.stop()
michael@0 339
michael@0 340 def createReftestProfile(self, options, reftestlist):
michael@0 341 profile = RefTest.createReftestProfile(self, options, reftestlist, server=options.remoteWebServer)
michael@0 342 profileDir = profile.profile
michael@0 343
michael@0 344 prefs = {}
michael@0 345 prefs["browser.firstrun.show.localepicker"] = False
michael@0 346 prefs["font.size.inflation.emPerLine"] = 0
michael@0 347 prefs["font.size.inflation.minTwips"] = 0
michael@0 348 prefs["reftest.remote"] = True
michael@0 349 # Set a future policy version to avoid the telemetry prompt.
michael@0 350 prefs["toolkit.telemetry.prompted"] = 999
michael@0 351 prefs["toolkit.telemetry.notifiedOptOut"] = 999
michael@0 352 prefs["reftest.uri"] = "%s" % reftestlist
michael@0 353 prefs["datareporting.policy.dataSubmissionPolicyBypassAcceptance"] = True
michael@0 354
michael@0 355 # Point the url-classifier to the local testing server for fast failures
michael@0 356 prefs["browser.safebrowsing.gethashURL"] = "http://127.0.0.1:8888/safebrowsing-dummy/gethash"
michael@0 357 prefs["browser.safebrowsing.updateURL"] = "http://127.0.0.1:8888/safebrowsing-dummy/update"
michael@0 358 # Point update checks to the local testing server for fast failures
michael@0 359 prefs["extensions.update.url"] = "http://127.0.0.1:8888/extensions-dummy/updateURL"
michael@0 360 prefs["extensions.update.background.url"] = "http://127.0.0.1:8888/extensions-dummy/updateBackgroundURL"
michael@0 361 prefs["extensions.blocklist.url"] = "http://127.0.0.1:8888/extensions-dummy/blocklistURL"
michael@0 362 prefs["extensions.hotfix.url"] = "http://127.0.0.1:8888/extensions-dummy/hotfixURL"
michael@0 363 # Turn off extension updates so they don't bother tests
michael@0 364 prefs["extensions.update.enabled"] = False
michael@0 365 # Make sure opening about:addons won't hit the network
michael@0 366 prefs["extensions.webservice.discoverURL"] = "http://127.0.0.1:8888/extensions-dummy/discoveryURL"
michael@0 367 # Make sure AddonRepository won't hit the network
michael@0 368 prefs["extensions.getAddons.maxResults"] = 0
michael@0 369 prefs["extensions.getAddons.get.url"] = "http://127.0.0.1:8888/extensions-dummy/repositoryGetURL"
michael@0 370 prefs["extensions.getAddons.getWithPerformance.url"] = "http://127.0.0.1:8888/extensions-dummy/repositoryGetWithPerformanceURL"
michael@0 371 prefs["extensions.getAddons.search.browseURL"] = "http://127.0.0.1:8888/extensions-dummy/repositoryBrowseURL"
michael@0 372 prefs["extensions.getAddons.search.url"] = "http://127.0.0.1:8888/extensions-dummy/repositorySearchURL"
michael@0 373 # Make sure that opening the plugins check page won't hit the network
michael@0 374 prefs["plugins.update.url"] = "http://127.0.0.1:8888/plugins-dummy/updateCheckURL"
michael@0 375 prefs["layout.css.devPixelsPerPx"] = "1.0"
michael@0 376
michael@0 377 # Disable skia-gl: see bug 907351
michael@0 378 prefs["gfx.canvas.azure.accelerated"] = False
michael@0 379
michael@0 380 # Set the extra prefs.
michael@0 381 profile.set_preferences(prefs)
michael@0 382
michael@0 383 try:
michael@0 384 self._devicemanager.pushDir(profileDir, options.remoteProfile)
michael@0 385 except devicemanager.DMError:
michael@0 386 print "Automation Error: Failed to copy profiledir to device"
michael@0 387 raise
michael@0 388
michael@0 389 return profile
michael@0 390
michael@0 391 def copyExtraFilesToProfile(self, options, profile):
michael@0 392 profileDir = profile.profile
michael@0 393 RefTest.copyExtraFilesToProfile(self, options, profile)
michael@0 394 try:
michael@0 395 self._devicemanager.pushDir(profileDir, options.remoteProfile)
michael@0 396 except devicemanager.DMError:
michael@0 397 print "Automation Error: Failed to copy extra files to device"
michael@0 398 raise
michael@0 399
michael@0 400 def getManifestPath(self, path):
michael@0 401 return path
michael@0 402
michael@0 403 def printDeviceInfo(self, printLogcat=False):
michael@0 404 try:
michael@0 405 if printLogcat:
michael@0 406 logcat = self._devicemanager.getLogcat(filterOutRegexps=fennecLogcatFilters)
michael@0 407 print ''.join(logcat)
michael@0 408 print "Device info: %s" % self._devicemanager.getInfo()
michael@0 409 print "Test root: %s" % self._devicemanager.getDeviceRoot()
michael@0 410 except devicemanager.DMError:
michael@0 411 print "WARNING: Error getting device information"
michael@0 412
michael@0 413 def cleanup(self, profileDir):
michael@0 414 # Pull results back from device
michael@0 415 if self.remoteLogFile and \
michael@0 416 self._devicemanager.fileExists(self.remoteLogFile):
michael@0 417 self._devicemanager.getFile(self.remoteLogFile, self.localLogName)
michael@0 418 else:
michael@0 419 print "WARNING: Unable to retrieve log file (%s) from remote " \
michael@0 420 "device" % self.remoteLogFile
michael@0 421 self._devicemanager.removeDir(self.remoteProfile)
michael@0 422 self._devicemanager.removeDir(self.remoteTestRoot)
michael@0 423 RefTest.cleanup(self, profileDir)
michael@0 424 if (self.pidFile != ""):
michael@0 425 try:
michael@0 426 os.remove(self.pidFile)
michael@0 427 os.remove(self.pidFile + ".xpcshell.pid")
michael@0 428 except:
michael@0 429 print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % self.pidFile
michael@0 430
michael@0 431 def main(args):
michael@0 432 automation = RemoteAutomation(None)
michael@0 433 parser = RemoteOptions(automation)
michael@0 434 options, args = parser.parse_args()
michael@0 435
michael@0 436 if (options.deviceIP == None):
michael@0 437 print "Error: you must provide a device IP to connect to via the --device option"
michael@0 438 return 1
michael@0 439
michael@0 440 try:
michael@0 441 if (options.dm_trans == "adb"):
michael@0 442 if (options.deviceIP):
michael@0 443 dm = droid.DroidADB(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
michael@0 444 else:
michael@0 445 dm = droid.DroidADB(None, None, deviceRoot=options.remoteTestRoot)
michael@0 446 else:
michael@0 447 dm = droid.DroidSUT(options.deviceIP, options.devicePort, deviceRoot=options.remoteTestRoot)
michael@0 448 except devicemanager.DMError:
michael@0 449 print "Automation Error: exception while initializing devicemanager. Most likely the device is not in a testable state."
michael@0 450 return 1
michael@0 451
michael@0 452 automation.setDeviceManager(dm)
michael@0 453
michael@0 454 if (options.remoteProductName != None):
michael@0 455 automation.setProduct(options.remoteProductName)
michael@0 456
michael@0 457 # Set up the defaults and ensure options are set
michael@0 458 options = parser.verifyRemoteOptions(options)
michael@0 459 if (options == None):
michael@0 460 print "ERROR: Invalid options specified, use --help for a list of valid options"
michael@0 461 return 1
michael@0 462
michael@0 463 if not options.ignoreWindowSize:
michael@0 464 parts = dm.getInfo('screen')['screen'][0].split()
michael@0 465 width = int(parts[0].split(':')[1])
michael@0 466 height = int(parts[1].split(':')[1])
michael@0 467 if (width < 1050 or height < 1050):
michael@0 468 print "ERROR: Invalid screen resolution %sx%s, please adjust to 1366x1050 or higher" % (width, height)
michael@0 469 return 1
michael@0 470
michael@0 471 automation.setAppName(options.app)
michael@0 472 automation.setRemoteProfile(options.remoteProfile)
michael@0 473 automation.setRemoteLog(options.remoteLogFile)
michael@0 474 reftest = RemoteReftest(automation, dm, options, SCRIPT_DIRECTORY)
michael@0 475 options = parser.verifyCommonOptions(options, reftest)
michael@0 476
michael@0 477 # Hack in a symbolic link for jsreftest
michael@0 478 os.system("ln -s ../jsreftest " + str(os.path.join(SCRIPT_DIRECTORY, "jsreftest")))
michael@0 479
michael@0 480 # Dynamically build the reftest URL if possible, beware that args[0] should exist 'inside' the webroot
michael@0 481 manifest = args[0]
michael@0 482 if os.path.exists(os.path.join(SCRIPT_DIRECTORY, args[0])):
michael@0 483 manifest = "http://" + str(options.remoteWebServer) + ":" + str(options.httpPort) + "/" + args[0]
michael@0 484 elif os.path.exists(args[0]):
michael@0 485 manifestPath = os.path.abspath(args[0]).split(SCRIPT_DIRECTORY)[1].strip('/')
michael@0 486 manifest = "http://" + str(options.remoteWebServer) + ":" + str(options.httpPort) + "/" + manifestPath
michael@0 487 else:
michael@0 488 print "ERROR: Could not find test manifest '%s'" % manifest
michael@0 489 return 1
michael@0 490
michael@0 491 # Start the webserver
michael@0 492 retVal = reftest.startWebServer(options)
michael@0 493 if retVal:
michael@0 494 return retVal
michael@0 495
michael@0 496 procName = options.app.split('/')[-1]
michael@0 497 if (dm.processExist(procName)):
michael@0 498 dm.killProcess(procName)
michael@0 499
michael@0 500 reftest.printDeviceInfo()
michael@0 501
michael@0 502 #an example manifest name to use on the cli
michael@0 503 # manifest = "http://" + options.remoteWebServer + "/reftests/layout/reftests/reftest-sanity/reftest.list"
michael@0 504 retVal = 0
michael@0 505 try:
michael@0 506 cmdlineArgs = ["-reftest", manifest]
michael@0 507 if options.bootstrap:
michael@0 508 cmdlineArgs = []
michael@0 509 dm.recordLogcat()
michael@0 510 retVal = reftest.runTests(manifest, options, cmdlineArgs)
michael@0 511 except:
michael@0 512 print "Automation Error: Exception caught while running tests"
michael@0 513 traceback.print_exc()
michael@0 514 retVal = 1
michael@0 515
michael@0 516 reftest.stopWebServer(options)
michael@0 517
michael@0 518 reftest.printDeviceInfo(printLogcat=True)
michael@0 519
michael@0 520 return retVal
michael@0 521
michael@0 522 if __name__ == "__main__":
michael@0 523 sys.exit(main(sys.argv[1:]))
michael@0 524

mercurial