2010-03-24 10:51:17 -07:00
|
|
|
# ***** BEGIN LICENSE BLOCK *****
|
|
|
|
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
#
|
|
|
|
# The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
# 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
# the License. You may obtain a copy of the License at
|
|
|
|
# http://www.mozilla.org/MPL/
|
|
|
|
#
|
|
|
|
# Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
# for the specific language governing rights and limitations under the
|
|
|
|
# License.
|
|
|
|
#
|
|
|
|
# The Original Code is mozilla.org code.
|
|
|
|
#
|
|
|
|
# The Initial Developer of the Original Code is Joel Maher.
|
|
|
|
#
|
|
|
|
# Portions created by the Initial Developer are Copyright (C) 2010
|
|
|
|
# the Initial Developer. All Rights Reserved.
|
|
|
|
#
|
|
|
|
# Contributor(s):
|
|
|
|
# Joel Maher <joel.maher@gmail.com> (Original Developer)
|
|
|
|
#
|
|
|
|
# Alternatively, the contents of this file may be used under the terms of
|
|
|
|
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
# in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
# of those above. If you wish to allow use of your version of this file only
|
|
|
|
# under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
# use your version of this file under the terms of the MPL, indicate your
|
|
|
|
# decision by deleting the provisions above and replace them with the notice
|
|
|
|
# and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
# the provisions above, a recipient may use your version of this file under
|
|
|
|
# the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
#
|
|
|
|
# ***** END LICENSE BLOCK *****
|
|
|
|
|
2010-03-15 15:35:59 -07:00
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
import time
|
|
|
|
|
|
|
|
SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
|
|
|
|
sys.path.append(SCRIPT_DIRECTORY)
|
|
|
|
#os.chdir(SCRIPT_DIRECTORY)
|
|
|
|
|
|
|
|
from runreftest import RefTest
|
|
|
|
from runreftest import ReftestOptions
|
|
|
|
from automation import Automation
|
|
|
|
from devicemanager import DeviceManager
|
|
|
|
|
|
|
|
class RemoteAutomation(Automation):
|
|
|
|
_devicemanager = None
|
|
|
|
|
|
|
|
def __init__(self, deviceManager, product = ''):
|
|
|
|
self._devicemanager = deviceManager
|
|
|
|
self._product = product
|
|
|
|
Automation.__init__(self)
|
|
|
|
|
|
|
|
def setDeviceManager(self, deviceManager):
|
|
|
|
self._devicemanager = deviceManager
|
|
|
|
|
|
|
|
def setProduct(self, productName):
|
|
|
|
self._product = productName
|
|
|
|
|
|
|
|
def setRemoteApp(self, remoteAppName):
|
|
|
|
self._remoteAppName = remoteAppName
|
|
|
|
|
|
|
|
def setTestRoot(self, testRoot):
|
|
|
|
self._testRoot = testRoot
|
|
|
|
|
|
|
|
def waitForFinish(self, proc, utilityPath, timeout, maxTime, startTime):
|
|
|
|
status = proc.wait()
|
|
|
|
print proc.stdout
|
|
|
|
# todo: consider pulling log file from remote
|
|
|
|
return status
|
|
|
|
|
|
|
|
def buildCommandLine(self, app, debuggerInfo, profileDir, testURL, extraArgs):
|
|
|
|
remoteProfileDir = self._testRoot + 'profile'
|
|
|
|
cmd, args = Automation.buildCommandLine(self, app, debuggerInfo, remoteProfileDir, testURL, extraArgs)
|
|
|
|
return app, ['--environ:NO_EM_RESTART=1'] + args
|
|
|
|
|
|
|
|
def Process(self, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
|
|
|
return self.RProcess(self._devicemanager, self._remoteAppName, cmd, stdout, stderr, env, cwd)
|
|
|
|
|
|
|
|
class RProcess(object):
|
|
|
|
#device manager process
|
|
|
|
dm = None
|
|
|
|
def __init__(self, dm, appName, cmd, stdout = None, stderr = None, env = None, cwd = '.'):
|
|
|
|
self.dm = dm
|
|
|
|
print "going to launch process: " + str(self.dm.host)
|
|
|
|
self.proc = dm.launchProcess(cmd)
|
|
|
|
self.procName = appName
|
2010-03-24 10:51:17 -07:00
|
|
|
|
|
|
|
# Setting this at 1 hour since remote testing is much slower
|
|
|
|
self.timeout = 3600
|
2010-03-15 15:35:59 -07:00
|
|
|
time.sleep(5)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def pid(self):
|
|
|
|
hexpid = self.dm.processExist(self.procName)
|
|
|
|
if (hexpid == '' or hexpid == None):
|
|
|
|
hexpid = 0
|
|
|
|
return int(hexpid, 0)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def stdout(self):
|
|
|
|
return self.dm.getFile(self.proc)
|
|
|
|
|
2010-03-24 10:51:17 -07:00
|
|
|
def wait(self, timeout = None):
|
2010-03-15 15:35:59 -07:00
|
|
|
timer = 0
|
2010-03-24 10:51:17 -07:00
|
|
|
if timeout == None:
|
|
|
|
timeout = self.timeout
|
|
|
|
|
2010-03-15 15:35:59 -07:00
|
|
|
while (self.dm.process.isAlive()):
|
|
|
|
time.sleep(1)
|
|
|
|
timer += 1
|
2010-03-24 10:51:17 -07:00
|
|
|
if (timer > timeout):
|
2010-03-15 15:35:59 -07:00
|
|
|
break
|
|
|
|
|
2010-03-24 10:51:17 -07:00
|
|
|
if (timer >= timeout):
|
2010-03-15 15:35:59 -07:00
|
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
|
|
def kill(self):
|
|
|
|
self.dm.killProcess(self.procName)
|
|
|
|
|
|
|
|
|
|
|
|
class RemoteOptions(ReftestOptions):
|
|
|
|
def __init__(self, automation):
|
|
|
|
ReftestOptions.__init__(self, automation)
|
|
|
|
|
|
|
|
defaults = {}
|
|
|
|
defaults["logFile"] = "reftest.log"
|
|
|
|
# app, xrePath and utilityPath variables are set in main function
|
|
|
|
defaults["testRoot"] = "/tests/"
|
|
|
|
defaults["app"] = ""
|
|
|
|
defaults["xrePath"] = ""
|
|
|
|
defaults["utilityPath"] = ""
|
|
|
|
|
|
|
|
self.add_option("--device", action="store",
|
|
|
|
type = "string", dest = "device",
|
|
|
|
help = "ip address of remote device to test")
|
|
|
|
defaults["device"] = None
|
|
|
|
|
|
|
|
self.add_option("--devicePort", action="store",
|
|
|
|
type = "string", dest = "devicePort",
|
|
|
|
help = "port of remote device to test")
|
|
|
|
defaults["devicePort"] = 27020
|
|
|
|
|
|
|
|
self.add_option("--remoteProductName", action="store",
|
|
|
|
type = "string", dest = "remoteProductName",
|
|
|
|
help = "Name of remote product to test - either fennec or firefox, defaults to fennec")
|
|
|
|
defaults["remoteProductName"] = "fennec"
|
|
|
|
|
|
|
|
self.add_option("--remoteAppName", action="store",
|
|
|
|
type = "string", dest = "remoteAppName",
|
|
|
|
help = "Executable name for remote device, OS dependent, defaults to fennec.exe")
|
|
|
|
defaults["remoteAppName"] = "fennec.exe"
|
|
|
|
|
|
|
|
self.add_option("--remote-webserver", action="store",
|
|
|
|
type = "string", dest = "remoteWebServer",
|
|
|
|
help = "IP Address of the webserver hosting the reftest content")
|
|
|
|
defaults["remoteWebServer"] = "127.0.0.1"
|
|
|
|
|
|
|
|
self.set_defaults(**defaults)
|
|
|
|
|
|
|
|
class RemoteReftest(RefTest):
|
|
|
|
remoteApp = ''
|
|
|
|
|
|
|
|
def __init__(self, automation, devicemanager, options, scriptDir):
|
|
|
|
RefTest.__init__(self, automation)
|
|
|
|
self._devicemanager = devicemanager
|
|
|
|
self.scriptDir = scriptDir
|
|
|
|
self.remoteApp = options.app
|
|
|
|
self.remoteTestRoot = options.testRoot
|
|
|
|
self.remoteProfileDir = options.testRoot + 'profile'
|
|
|
|
|
|
|
|
def createReftestProfile(self, options, profileDir):
|
|
|
|
RefTest.createReftestProfile(self, options, profileDir)
|
|
|
|
|
|
|
|
self.remoteTestRoot += "reftest/"
|
|
|
|
|
|
|
|
# install the reftest extension bits into the remoteProfile
|
|
|
|
profileExtensionsPath = os.path.join(profileDir, "extensions")
|
|
|
|
reftestExtensionPath = self.remoteTestRoot.replace('/', '\\')
|
|
|
|
extFile = open(os.path.join(profileExtensionsPath, "reftest@mozilla.org"), "w")
|
|
|
|
extFile.write(reftestExtensionPath)
|
|
|
|
extFile.close()
|
|
|
|
|
|
|
|
if (self._devicemanager.pushDir(profileDir, self.remoteProfileDir) == None):
|
|
|
|
raise devicemanager.FileError("Failed to copy profiledir to device")
|
|
|
|
|
|
|
|
if (self._devicemanager.pushDir(self.scriptDir + '/reftest', self.remoteTestRoot) == None):
|
|
|
|
raise devicemanager.FileError("Failed to copy extension dir to device")
|
|
|
|
|
|
|
|
|
|
|
|
def copyExtraFilesToProfile(self, options, profileDir):
|
|
|
|
RefTest.copyExtraFilesToProfile(self, options, profileDir)
|
|
|
|
if (self._devicemanager.pushDir(profileDir, self.remoteProfileDir) == None):
|
|
|
|
raise devicemanager.FileError("Failed to copy extra files in profile dir to device")
|
|
|
|
|
|
|
|
def registerExtension(self, browserEnv, options, profileDir):
|
|
|
|
"""
|
|
|
|
It appears that we do not need to do the extension registration on winmo.
|
|
|
|
This is something we should look into for winmo as the -silent option isn't working
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
def getManifestPath(self, path):
|
|
|
|
return path
|
|
|
|
|
|
|
|
def cleanup(self, profileDir):
|
|
|
|
self._devicemanager.removeDir(self.remoteProfileDir)
|
|
|
|
self._devicemanager.removeDir(self.remoteTestRoot)
|
|
|
|
RefTest.cleanup(self, profileDir)
|
|
|
|
|
|
|
|
def main():
|
|
|
|
dm = DeviceManager(None, None)
|
|
|
|
automation = RemoteAutomation(dm)
|
|
|
|
parser = RemoteOptions(automation)
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
|
|
|
|
if (options.device == None):
|
|
|
|
print "Error: you must provide a device IP to connect to via the --device option"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if options.remoteAppName.rfind('/') < 0:
|
|
|
|
options.app = options.testRoot + options.remoteProductName + '/'
|
|
|
|
options.app += str(options.remoteAppName)
|
|
|
|
|
|
|
|
options.xrePath = options.testRoot + options.remoteProductName + '/xulrunner'
|
|
|
|
options.utilityPath = options.testRoot + options.remoteProductName + '/bin'
|
|
|
|
|
|
|
|
dm = DeviceManager(options.device, options.devicePort)
|
|
|
|
automation.setDeviceManager(dm)
|
|
|
|
automation.setProduct(options.remoteProductName)
|
|
|
|
automation.setRemoteApp(options.remoteAppName)
|
|
|
|
automation.setTestRoot(options.testRoot)
|
|
|
|
reftest = RemoteReftest(automation, dm, options, SCRIPT_DIRECTORY)
|
|
|
|
|
|
|
|
if (options.remoteWebServer == "127.0.0.1"):
|
|
|
|
print "Error: remoteWebServer must be non localhost"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
#an example manifest name to use on the cli
|
|
|
|
# manifest = "http://" + options.remoteWebServer + "/reftests/layout/reftests/reftest-sanity/reftest.list"
|
|
|
|
reftest.runTests(args[0], options)
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|