1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/tools/reftest/runreftestb2g.py Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,607 @@ 1.4 +# This Source Code Form is subject to the terms of the Mozilla Public 1.5 +# License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 +# You can obtain one at http://mozilla.org/MPL/2.0/. 1.7 + 1.8 +import ConfigParser 1.9 +import os 1.10 +import sys 1.11 +import tempfile 1.12 +import traceback 1.13 + 1.14 +# We need to know our current directory so that we can serve our test files from it. 1.15 +here = os.path.abspath(os.path.dirname(__file__)) 1.16 + 1.17 +from automation import Automation 1.18 +from b2gautomation import B2GRemoteAutomation 1.19 +from b2g_desktop import run_desktop_reftests 1.20 +from runreftest import RefTest 1.21 +from runreftest import ReftestOptions 1.22 +from remotereftest import ReftestServer 1.23 + 1.24 +from mozdevice import DeviceManagerADB, DMError 1.25 +from marionette import Marionette 1.26 +import moznetwork 1.27 + 1.28 +class B2GOptions(ReftestOptions): 1.29 + 1.30 + def __init__(self, automation=None, **kwargs): 1.31 + defaults = {} 1.32 + if not automation: 1.33 + automation = B2GRemoteAutomation(None, "fennec", context_chrome=True) 1.34 + 1.35 + ReftestOptions.__init__(self, automation) 1.36 + 1.37 + self.add_option("--browser-arg", action="store", 1.38 + type = "string", dest = "browser_arg", 1.39 + help = "Optional command-line arg to pass to the browser") 1.40 + defaults["browser_arg"] = None 1.41 + 1.42 + self.add_option("--b2gpath", action="store", 1.43 + type = "string", dest = "b2gPath", 1.44 + help = "path to B2G repo or qemu dir") 1.45 + defaults["b2gPath"] = None 1.46 + 1.47 + self.add_option("--marionette", action="store", 1.48 + type = "string", dest = "marionette", 1.49 + help = "host:port to use when connecting to Marionette") 1.50 + defaults["marionette"] = None 1.51 + 1.52 + self.add_option("--emulator", action="store", 1.53 + type="string", dest = "emulator", 1.54 + help = "Architecture of emulator to use: x86 or arm") 1.55 + defaults["emulator"] = None 1.56 + self.add_option("--emulator-res", action="store", 1.57 + type="string", dest = "emulator_res", 1.58 + help = "Emulator resolution of the format '<width>x<height>'") 1.59 + defaults["emulator_res"] = None 1.60 + 1.61 + self.add_option("--no-window", action="store_true", 1.62 + dest = "noWindow", 1.63 + help = "Pass --no-window to the emulator") 1.64 + defaults["noWindow"] = False 1.65 + 1.66 + self.add_option("--adbpath", action="store", 1.67 + type = "string", dest = "adbPath", 1.68 + help = "path to adb") 1.69 + defaults["adbPath"] = "adb" 1.70 + 1.71 + self.add_option("--deviceIP", action="store", 1.72 + type = "string", dest = "deviceIP", 1.73 + help = "ip address of remote device to test") 1.74 + defaults["deviceIP"] = None 1.75 + 1.76 + self.add_option("--devicePort", action="store", 1.77 + type = "string", dest = "devicePort", 1.78 + help = "port of remote device to test") 1.79 + defaults["devicePort"] = 20701 1.80 + 1.81 + self.add_option("--remote-logfile", action="store", 1.82 + type = "string", dest = "remoteLogFile", 1.83 + help = "Name of log file on the device relative to the device root. PLEASE ONLY USE A FILENAME.") 1.84 + defaults["remoteLogFile"] = None 1.85 + 1.86 + self.add_option("--remote-webserver", action = "store", 1.87 + type = "string", dest = "remoteWebServer", 1.88 + help = "ip address where the remote web server is hosted at") 1.89 + defaults["remoteWebServer"] = None 1.90 + 1.91 + self.add_option("--http-port", action = "store", 1.92 + type = "string", dest = "httpPort", 1.93 + help = "ip address where the remote web server is hosted at") 1.94 + defaults["httpPort"] = automation.DEFAULT_HTTP_PORT 1.95 + 1.96 + self.add_option("--ssl-port", action = "store", 1.97 + type = "string", dest = "sslPort", 1.98 + help = "ip address where the remote web server is hosted at") 1.99 + defaults["sslPort"] = automation.DEFAULT_SSL_PORT 1.100 + 1.101 + self.add_option("--pidfile", action = "store", 1.102 + type = "string", dest = "pidFile", 1.103 + help = "name of the pidfile to generate") 1.104 + defaults["pidFile"] = "" 1.105 + self.add_option("--gecko-path", action="store", 1.106 + type="string", dest="geckoPath", 1.107 + help="the path to a gecko distribution that should " 1.108 + "be installed on the emulator prior to test") 1.109 + defaults["geckoPath"] = None 1.110 + self.add_option("--logcat-dir", action="store", 1.111 + type="string", dest="logcat_dir", 1.112 + help="directory to store logcat dump files") 1.113 + defaults["logcat_dir"] = None 1.114 + self.add_option('--busybox', action='store', 1.115 + type='string', dest='busybox', 1.116 + help="Path to busybox binary to install on device") 1.117 + defaults['busybox'] = None 1.118 + self.add_option("--httpd-path", action = "store", 1.119 + type = "string", dest = "httpdPath", 1.120 + help = "path to the httpd.js file") 1.121 + defaults["httpdPath"] = None 1.122 + self.add_option("--profile", action="store", 1.123 + type="string", dest="profile", 1.124 + help="for desktop testing, the path to the " 1.125 + "gaia profile to use") 1.126 + defaults["profile"] = None 1.127 + self.add_option("--desktop", action="store_true", 1.128 + dest="desktop", 1.129 + help="Run the tests on a B2G desktop build") 1.130 + defaults["desktop"] = False 1.131 + defaults["remoteTestRoot"] = "/data/local/tests" 1.132 + defaults["logFile"] = "reftest.log" 1.133 + defaults["autorun"] = True 1.134 + defaults["closeWhenDone"] = True 1.135 + defaults["testPath"] = "" 1.136 + defaults["runTestsInParallel"] = False 1.137 + 1.138 + self.set_defaults(**defaults) 1.139 + 1.140 + def verifyRemoteOptions(self, options): 1.141 + if options.runTestsInParallel: 1.142 + self.error("Cannot run parallel tests here") 1.143 + 1.144 + if not options.remoteTestRoot: 1.145 + options.remoteTestRoot = self.automation._devicemanager.getDeviceRoot() + "/reftest" 1.146 + options.remoteProfile = options.remoteTestRoot + "/profile" 1.147 + 1.148 + productRoot = options.remoteTestRoot + "/" + self.automation._product 1.149 + if options.utilityPath == self.automation.DIST_BIN: 1.150 + options.utilityPath = productRoot + "/bin" 1.151 + 1.152 + if options.remoteWebServer == None: 1.153 + if os.name != "nt": 1.154 + options.remoteWebServer = moznetwork.get_ip() 1.155 + else: 1.156 + print "ERROR: you must specify a --remote-webserver=<ip address>\n" 1.157 + return None 1.158 + 1.159 + options.webServer = options.remoteWebServer 1.160 + 1.161 + if options.geckoPath and not options.emulator: 1.162 + self.error("You must specify --emulator if you specify --gecko-path") 1.163 + 1.164 + if options.logcat_dir and not options.emulator: 1.165 + self.error("You must specify --emulator if you specify --logcat-dir") 1.166 + 1.167 + #if not options.emulator and not options.deviceIP: 1.168 + # print "ERROR: you must provide a device IP" 1.169 + # return None 1.170 + 1.171 + if options.remoteLogFile == None: 1.172 + options.remoteLogFile = "reftest.log" 1.173 + 1.174 + options.localLogName = options.remoteLogFile 1.175 + options.remoteLogFile = options.remoteTestRoot + '/' + options.remoteLogFile 1.176 + 1.177 + # Ensure that the options.logfile (which the base class uses) is set to 1.178 + # the remote setting when running remote. Also, if the user set the 1.179 + # log file name there, use that instead of reusing the remotelogfile as above. 1.180 + if (options.logFile): 1.181 + # If the user specified a local logfile name use that 1.182 + options.localLogName = options.logFile 1.183 + options.logFile = options.remoteLogFile 1.184 + 1.185 + # Only reset the xrePath if it wasn't provided 1.186 + if options.xrePath == None: 1.187 + options.xrePath = options.utilityPath 1.188 + options.xrePath = os.path.abspath(options.xrePath) 1.189 + 1.190 + if options.pidFile != "": 1.191 + f = open(options.pidFile, 'w') 1.192 + f.write("%s" % os.getpid()) 1.193 + f.close() 1.194 + 1.195 + # httpd-path is specified by standard makefile targets and may be specified 1.196 + # on the command line to select a particular version of httpd.js. If not 1.197 + # specified, try to select the one from from the xre bundle, as required in bug 882932. 1.198 + if not options.httpdPath: 1.199 + options.httpdPath = os.path.join(options.xrePath, "components") 1.200 + 1.201 + return options 1.202 + 1.203 + 1.204 +class ProfileConfigParser(ConfigParser.RawConfigParser): 1.205 + """Subclass of RawConfigParser that outputs .ini files in the exact 1.206 + format expected for profiles.ini, which is slightly different 1.207 + than the default format. 1.208 + """ 1.209 + 1.210 + def optionxform(self, optionstr): 1.211 + return optionstr 1.212 + 1.213 + def write(self, fp): 1.214 + if self._defaults: 1.215 + fp.write("[%s]\n" % ConfigParser.DEFAULTSECT) 1.216 + for (key, value) in self._defaults.items(): 1.217 + fp.write("%s=%s\n" % (key, str(value).replace('\n', '\n\t'))) 1.218 + fp.write("\n") 1.219 + for section in self._sections: 1.220 + fp.write("[%s]\n" % section) 1.221 + for (key, value) in self._sections[section].items(): 1.222 + if key == "__name__": 1.223 + continue 1.224 + if (value is not None) or (self._optcre == self.OPTCRE): 1.225 + key = "=".join((key, str(value).replace('\n', '\n\t'))) 1.226 + fp.write("%s\n" % (key)) 1.227 + fp.write("\n") 1.228 + 1.229 +class B2GRemoteReftest(RefTest): 1.230 + 1.231 + _devicemanager = None 1.232 + localProfile = None 1.233 + remoteApp = '' 1.234 + profile = None 1.235 + 1.236 + def __init__(self, automation, devicemanager, options, scriptDir): 1.237 + RefTest.__init__(self, automation) 1.238 + self._devicemanager = devicemanager 1.239 + self.runSSLTunnel = False 1.240 + self.remoteTestRoot = options.remoteTestRoot 1.241 + self.remoteProfile = options.remoteProfile 1.242 + self.automation.setRemoteProfile(self.remoteProfile) 1.243 + self.localLogName = options.localLogName 1.244 + self.remoteLogFile = options.remoteLogFile 1.245 + self.bundlesDir = '/system/b2g/distribution/bundles' 1.246 + self.userJS = '/data/local/user.js' 1.247 + self.remoteMozillaPath = '/data/b2g/mozilla' 1.248 + self.remoteProfilesIniPath = os.path.join(self.remoteMozillaPath, 'profiles.ini') 1.249 + self.originalProfilesIni = None 1.250 + self.scriptDir = scriptDir 1.251 + self.SERVER_STARTUP_TIMEOUT = 90 1.252 + if self.automation.IS_DEBUG_BUILD: 1.253 + self.SERVER_STARTUP_TIMEOUT = 180 1.254 + 1.255 + def cleanup(self, profileDir): 1.256 + # Pull results back from device 1.257 + if (self.remoteLogFile): 1.258 + try: 1.259 + self._devicemanager.getFile(self.remoteLogFile, self.localLogName) 1.260 + except: 1.261 + print "ERROR: We were not able to retrieve the info from %s" % self.remoteLogFile 1.262 + sys.exit(5) 1.263 + 1.264 + # Delete any bundled extensions 1.265 + if profileDir: 1.266 + extensionDir = os.path.join(profileDir, 'extensions', 'staged') 1.267 + for filename in os.listdir(extensionDir): 1.268 + try: 1.269 + self._devicemanager._checkCmd(['shell', 'rm', '-rf', 1.270 + os.path.join(self.bundlesDir, filename)]) 1.271 + except DMError: 1.272 + pass 1.273 + 1.274 + # Restore the original profiles.ini. 1.275 + if self.originalProfilesIni: 1.276 + try: 1.277 + if not self.automation._is_emulator: 1.278 + self.restoreProfilesIni() 1.279 + os.remove(self.originalProfilesIni) 1.280 + except: 1.281 + pass 1.282 + 1.283 + if not self.automation._is_emulator: 1.284 + self._devicemanager.removeFile(self.remoteLogFile) 1.285 + self._devicemanager.removeDir(self.remoteProfile) 1.286 + self._devicemanager.removeDir(self.remoteTestRoot) 1.287 + 1.288 + # Restore the original user.js. 1.289 + self._devicemanager._checkCmd(['shell', 'rm', '-f', self.userJS]) 1.290 + self._devicemanager._checkCmd(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS]) 1.291 + 1.292 + # We've restored the original profile, so reboot the device so that 1.293 + # it gets picked up. 1.294 + self.automation.rebootDevice() 1.295 + 1.296 + RefTest.cleanup(self, profileDir) 1.297 + if getattr(self, 'pidFile', '') != '': 1.298 + try: 1.299 + os.remove(self.pidFile) 1.300 + os.remove(self.pidFile + ".xpcshell.pid") 1.301 + except: 1.302 + print "Warning: cleaning up pidfile '%s' was unsuccessful from the test harness" % self.pidFile 1.303 + 1.304 + def findPath(self, paths, filename = None): 1.305 + for path in paths: 1.306 + p = path 1.307 + if filename: 1.308 + p = os.path.join(p, filename) 1.309 + if os.path.exists(self.getFullPath(p)): 1.310 + return path 1.311 + return None 1.312 + 1.313 + def startWebServer(self, options): 1.314 + """ Create the webserver on the host and start it up """ 1.315 + remoteXrePath = options.xrePath 1.316 + remoteProfilePath = self.remoteProfile 1.317 + remoteUtilityPath = options.utilityPath 1.318 + localAutomation = Automation() 1.319 + localAutomation.IS_WIN32 = False 1.320 + localAutomation.IS_LINUX = False 1.321 + localAutomation.IS_MAC = False 1.322 + localAutomation.UNIXISH = False 1.323 + hostos = sys.platform 1.324 + if hostos in ['mac', 'darwin']: 1.325 + localAutomation.IS_MAC = True 1.326 + elif hostos in ['linux', 'linux2']: 1.327 + localAutomation.IS_LINUX = True 1.328 + localAutomation.UNIXISH = True 1.329 + elif hostos in ['win32', 'win64']: 1.330 + localAutomation.BIN_SUFFIX = ".exe" 1.331 + localAutomation.IS_WIN32 = True 1.332 + 1.333 + paths = [options.xrePath, 1.334 + localAutomation.DIST_BIN, 1.335 + self.automation._product, 1.336 + os.path.join('..', self.automation._product)] 1.337 + options.xrePath = self.findPath(paths) 1.338 + if options.xrePath == None: 1.339 + print "ERROR: unable to find xulrunner path for %s, please specify with --xre-path" % (os.name) 1.340 + sys.exit(1) 1.341 + paths.append("bin") 1.342 + paths.append(os.path.join("..", "bin")) 1.343 + 1.344 + xpcshell = "xpcshell" 1.345 + if (os.name == "nt"): 1.346 + xpcshell += ".exe" 1.347 + 1.348 + if (options.utilityPath): 1.349 + paths.insert(0, options.utilityPath) 1.350 + options.utilityPath = self.findPath(paths, xpcshell) 1.351 + if options.utilityPath == None: 1.352 + print "ERROR: unable to find utility path for %s, please specify with --utility-path" % (os.name) 1.353 + sys.exit(1) 1.354 + 1.355 + xpcshell = os.path.join(options.utilityPath, xpcshell) 1.356 + if self.automation.elf_arm(xpcshell): 1.357 + raise Exception('xpcshell at %s is an ARM binary; please use ' 1.358 + 'the --utility-path argument to specify the path ' 1.359 + 'to a desktop version.' % xpcshell) 1.360 + 1.361 + options.serverProfilePath = tempfile.mkdtemp() 1.362 + self.server = ReftestServer(localAutomation, options, self.scriptDir) 1.363 + retVal = self.server.start() 1.364 + if retVal: 1.365 + return retVal 1.366 + 1.367 + if (options.pidFile != ""): 1.368 + f = open(options.pidFile + ".xpcshell.pid", 'w') 1.369 + f.write("%s" % self.server._process.pid) 1.370 + f.close() 1.371 + 1.372 + retVal = self.server.ensureReady(self.SERVER_STARTUP_TIMEOUT) 1.373 + if retVal: 1.374 + return retVal 1.375 + 1.376 + options.xrePath = remoteXrePath 1.377 + options.utilityPath = remoteUtilityPath 1.378 + options.profilePath = remoteProfilePath 1.379 + return 0 1.380 + 1.381 + def stopWebServer(self, options): 1.382 + if hasattr(self, 'server'): 1.383 + self.server.stop() 1.384 + 1.385 + def restoreProfilesIni(self): 1.386 + # restore profiles.ini on the device to its previous state 1.387 + if not self.originalProfilesIni or not os.access(self.originalProfilesIni, os.F_OK): 1.388 + raise DMError('Unable to install original profiles.ini; file not found: %s', 1.389 + self.originalProfilesIni) 1.390 + 1.391 + self._devicemanager.pushFile(self.originalProfilesIni, self.remoteProfilesIniPath) 1.392 + 1.393 + def updateProfilesIni(self, profilePath): 1.394 + # update profiles.ini on the device to point to the test profile 1.395 + self.originalProfilesIni = tempfile.mktemp() 1.396 + self._devicemanager.getFile(self.remoteProfilesIniPath, self.originalProfilesIni) 1.397 + 1.398 + config = ProfileConfigParser() 1.399 + config.read(self.originalProfilesIni) 1.400 + for section in config.sections(): 1.401 + if 'Profile' in section: 1.402 + config.set(section, 'IsRelative', 0) 1.403 + config.set(section, 'Path', profilePath) 1.404 + 1.405 + newProfilesIni = tempfile.mktemp() 1.406 + with open(newProfilesIni, 'wb') as configfile: 1.407 + config.write(configfile) 1.408 + 1.409 + self._devicemanager.pushFile(newProfilesIni, self.remoteProfilesIniPath) 1.410 + try: 1.411 + os.remove(newProfilesIni) 1.412 + except: 1.413 + pass 1.414 + 1.415 + 1.416 + def createReftestProfile(self, options, reftestlist): 1.417 + profile = RefTest.createReftestProfile(self, options, reftestlist, 1.418 + server=options.remoteWebServer, 1.419 + special_powers=False) 1.420 + profileDir = profile.profile 1.421 + 1.422 + prefs = {} 1.423 + # Turn off the locale picker screen 1.424 + prefs["browser.firstrun.show.localepicker"] = False 1.425 + prefs["browser.homescreenURL"] = "app://test-container.gaiamobile.org/index.html" 1.426 + prefs["browser.manifestURL"] = "app://test-container.gaiamobile.org/manifest.webapp" 1.427 + prefs["browser.tabs.remote"] = False 1.428 + prefs["dom.ipc.tabs.disabled"] = False 1.429 + prefs["dom.mozBrowserFramesEnabled"] = True 1.430 + prefs["font.size.inflation.emPerLine"] = 0 1.431 + prefs["font.size.inflation.minTwips"] = 0 1.432 + prefs["network.dns.localDomains"] = "app://test-container.gaiamobile.org" 1.433 + prefs["reftest.browser.iframe.enabled"] = False 1.434 + prefs["reftest.remote"] = True 1.435 + prefs["reftest.uri"] = "%s" % reftestlist 1.436 + # Set a future policy version to avoid the telemetry prompt. 1.437 + prefs["toolkit.telemetry.prompted"] = 999 1.438 + prefs["toolkit.telemetry.notifiedOptOut"] = 999 1.439 + 1.440 + # Set the extra prefs. 1.441 + profile.set_preferences(prefs) 1.442 + 1.443 + # Copy the profile to the device. 1.444 + self._devicemanager.removeDir(self.remoteProfile) 1.445 + try: 1.446 + self._devicemanager.pushDir(profileDir, self.remoteProfile) 1.447 + except DMError: 1.448 + print "Automation Error: Unable to copy profile to device." 1.449 + raise 1.450 + 1.451 + # Copy the extensions to the B2G bundles dir. 1.452 + extensionDir = os.path.join(profileDir, 'extensions', 'staged') 1.453 + # need to write to read-only dir 1.454 + self._devicemanager._checkCmd(['remount']) 1.455 + for filename in os.listdir(extensionDir): 1.456 + self._devicemanager._checkCmd(['shell', 'rm', '-rf', 1.457 + os.path.join(self.bundlesDir, filename)]) 1.458 + try: 1.459 + self._devicemanager.pushDir(extensionDir, self.bundlesDir) 1.460 + except DMError: 1.461 + print "Automation Error: Unable to copy extensions to device." 1.462 + raise 1.463 + 1.464 + # In B2G, user.js is always read from /data/local, not the profile 1.465 + # directory. Backup the original user.js first so we can restore it. 1.466 + self._devicemanager._checkCmd(['shell', 'rm', '-f', '%s.orig' % self.userJS]) 1.467 + self._devicemanager._checkCmd(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS]) 1.468 + self._devicemanager.pushFile(os.path.join(profileDir, "user.js"), self.userJS) 1.469 + 1.470 + self.updateProfilesIni(self.remoteProfile) 1.471 + 1.472 + options.profilePath = self.remoteProfile 1.473 + return profile 1.474 + 1.475 + def copyExtraFilesToProfile(self, options, profile): 1.476 + profileDir = profile.profile 1.477 + RefTest.copyExtraFilesToProfile(self, options, profile) 1.478 + try: 1.479 + self._devicemanager.pushDir(profileDir, options.remoteProfile) 1.480 + except DMError: 1.481 + print "Automation Error: Failed to copy extra files to device" 1.482 + raise 1.483 + 1.484 + def getManifestPath(self, path): 1.485 + return path 1.486 + 1.487 + 1.488 +def run_remote_reftests(parser, options, args): 1.489 + auto = B2GRemoteAutomation(None, "fennec", context_chrome=True) 1.490 + 1.491 + # create our Marionette instance 1.492 + kwargs = {} 1.493 + if options.emulator: 1.494 + kwargs['emulator'] = options.emulator 1.495 + auto.setEmulator(True) 1.496 + if options.noWindow: 1.497 + kwargs['noWindow'] = True 1.498 + if options.geckoPath: 1.499 + kwargs['gecko_path'] = options.geckoPath 1.500 + if options.logcat_dir: 1.501 + kwargs['logcat_dir'] = options.logcat_dir 1.502 + if options.busybox: 1.503 + kwargs['busybox'] = options.busybox 1.504 + if options.symbolsPath: 1.505 + kwargs['symbols_path'] = options.symbolsPath 1.506 + if options.emulator_res: 1.507 + kwargs['emulator_res'] = options.emulator_res 1.508 + if options.b2gPath: 1.509 + kwargs['homedir'] = options.b2gPath 1.510 + if options.marionette: 1.511 + host,port = options.marionette.split(':') 1.512 + kwargs['host'] = host 1.513 + kwargs['port'] = int(port) 1.514 + marionette = Marionette.getMarionetteOrExit(**kwargs) 1.515 + auto.marionette = marionette 1.516 + 1.517 + if options.emulator: 1.518 + dm = marionette.emulator.dm 1.519 + else: 1.520 + # create the DeviceManager 1.521 + kwargs = {'adbPath': options.adbPath, 1.522 + 'deviceRoot': options.remoteTestRoot} 1.523 + if options.deviceIP: 1.524 + kwargs.update({'host': options.deviceIP, 1.525 + 'port': options.devicePort}) 1.526 + dm = DeviagerADB(**kwargs) 1.527 + auto.setDeviceManager(dm) 1.528 + 1.529 + options = parser.verifyRemoteOptions(options) 1.530 + 1.531 + if (options == None): 1.532 + print "ERROR: Invalid options specified, use --help for a list of valid options" 1.533 + sys.exit(1) 1.534 + 1.535 + # TODO fix exception 1.536 + if not options.ignoreWindowSize: 1.537 + parts = dm.getInfo('screen')['screen'][0].split() 1.538 + width = int(parts[0].split(':')[1]) 1.539 + height = int(parts[1].split(':')[1]) 1.540 + if (width < 1366 or height < 1050): 1.541 + print "ERROR: Invalid screen resolution %sx%s, please adjust to 1366x1050 or higher" % (width, height) 1.542 + return 1 1.543 + 1.544 + auto.setProduct("b2g") 1.545 + auto.test_script = os.path.join(here, 'b2g_start_script.js') 1.546 + auto.test_script_args = [options.remoteWebServer, options.httpPort] 1.547 + auto.logFinish = "REFTEST TEST-START | Shutdown" 1.548 + 1.549 + reftest = B2GRemoteReftest(auto, dm, options, here) 1.550 + options = parser.verifyCommonOptions(options, reftest) 1.551 + 1.552 + logParent = os.path.dirname(options.remoteLogFile) 1.553 + dm.mkDir(logParent); 1.554 + auto.setRemoteLog(options.remoteLogFile) 1.555 + auto.setServerInfo(options.webServer, options.httpPort, options.sslPort) 1.556 + 1.557 + # Hack in a symbolic link for jsreftest 1.558 + os.system("ln -s %s %s" % (os.path.join('..', 'jsreftest'), os.path.join(here, 'jsreftest'))) 1.559 + 1.560 + # Dynamically build the reftest URL if possible, beware that args[0] should exist 'inside' the webroot 1.561 + manifest = args[0] 1.562 + if os.path.exists(os.path.join(here, args[0])): 1.563 + manifest = "http://%s:%s/%s" % (options.remoteWebServer, options.httpPort, args[0]) 1.564 + elif os.path.exists(args[0]): 1.565 + manifestPath = os.path.abspath(args[0]).split(here)[1].strip('/') 1.566 + manifest = "http://%s:%s/%s" % (options.remoteWebServer, options.httpPort, manifestPath) 1.567 + else: 1.568 + print "ERROR: Could not find test manifest '%s'" % manifest 1.569 + return 1 1.570 + 1.571 + # Start the webserver 1.572 + retVal = 1 1.573 + try: 1.574 + retVal = reftest.startWebServer(options) 1.575 + if retVal: 1.576 + return retVal 1.577 + procName = options.app.split('/')[-1] 1.578 + if (dm.processExist(procName)): 1.579 + dm.killProcess(procName) 1.580 + 1.581 + cmdlineArgs = ["-reftest", manifest] 1.582 + if getattr(options, 'bootstrap', False): 1.583 + cmdlineArgs = [] 1.584 + 1.585 + retVal = reftest.runTests(manifest, options, cmdlineArgs) 1.586 + except: 1.587 + print "Automation Error: Exception caught while running tests" 1.588 + traceback.print_exc() 1.589 + reftest.stopWebServer(options) 1.590 + try: 1.591 + reftest.cleanup(None) 1.592 + except: 1.593 + pass 1.594 + return 1 1.595 + 1.596 + reftest.stopWebServer(options) 1.597 + return retVal 1.598 + 1.599 +def main(args=sys.argv[1:]): 1.600 + parser = B2GOptions() 1.601 + options, args = parser.parse_args(args) 1.602 + 1.603 + if options.desktop: 1.604 + return run_desktop_reftests(parser, options, args) 1.605 + return run_remote_reftests(parser, options, args) 1.606 + 1.607 + 1.608 +if __name__ == "__main__": 1.609 + sys.exit(main()) 1.610 +