2010-03-13 21:57:06 +03:00
|
|
|
#!/usr/bin/env python
|
|
|
|
#
|
2012-05-21 15:12:37 +04: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-13 21:57:06 +03:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
import sys, os
|
2012-01-08 03:41:08 +04:00
|
|
|
import subprocess
|
2010-03-13 21:57:06 +03:00
|
|
|
import runxpcshelltests as xpcshell
|
2012-11-14 03:37:51 +04:00
|
|
|
import tempfile
|
2010-03-13 21:57:06 +03:00
|
|
|
from automationutils import *
|
2012-11-27 20:04:46 +04:00
|
|
|
from mozdevice import devicemanagerADB, devicemanagerSUT
|
|
|
|
|
|
|
|
here = os.path.dirname(os.path.abspath(__file__))
|
2010-03-13 21:57:06 +03:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
# A specialization of XPCShellTests that runs tests on an Android device
|
|
|
|
# via devicemanager.
|
2010-03-13 21:57:06 +03:00
|
|
|
class XPCShellRemote(xpcshell.XPCShellTests, object):
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
def __init__(self, devmgr, options, args):
|
2010-03-13 21:57:06 +03:00
|
|
|
xpcshell.XPCShellTests.__init__(self)
|
2012-11-27 20:04:46 +04:00
|
|
|
self.localLib = None
|
|
|
|
self.localBin = None
|
2011-08-22 12:00:50 +04:00
|
|
|
self.options = options
|
|
|
|
self.device = devmgr
|
|
|
|
self.pathMapping = []
|
|
|
|
self.remoteTestRoot = self.device.getTestRoot("xpcshell")
|
|
|
|
# Terse directory names are used here ("b" for a binaries directory)
|
|
|
|
# to minimize the length of the command line used to execute
|
|
|
|
# xpcshell on the remote device. adb has a limit to the number
|
|
|
|
# of characters used in a shell command, and the xpcshell command
|
|
|
|
# line can be quite complex.
|
|
|
|
self.remoteBinDir = self.remoteJoin(self.remoteTestRoot, "b")
|
2012-05-03 14:22:33 +04:00
|
|
|
self.remoteTmpDir = self.remoteJoin(self.remoteTestRoot, "tmp")
|
2011-08-22 12:00:50 +04:00
|
|
|
self.remoteScriptsDir = self.remoteTestRoot
|
|
|
|
self.remoteComponentsDir = self.remoteJoin(self.remoteTestRoot, "c")
|
2012-11-14 03:37:53 +04:00
|
|
|
self.remoteModulesDir = self.remoteJoin(self.remoteTestRoot, "m")
|
2011-08-22 12:00:50 +04:00
|
|
|
self.profileDir = self.remoteJoin(self.remoteTestRoot, "p")
|
2012-07-17 20:56:26 +04:00
|
|
|
self.remoteDebugger = options.debugger
|
|
|
|
self.remoteDebuggerArgs = options.debuggerArgs
|
2012-11-14 03:37:53 +04:00
|
|
|
self.testingModulesDir = options.testingModulesDir
|
2012-11-27 20:04:46 +04:00
|
|
|
|
|
|
|
if self.options.objdir:
|
|
|
|
self.xpcDir = os.path.join(self.options.objdir, "_tests/xpcshell")
|
|
|
|
elif os.path.isdir(os.path.join(here, 'tests')):
|
|
|
|
self.xpcDir = os.path.join(here, 'tests')
|
|
|
|
else:
|
|
|
|
print >> sys.stderr, "Couldn't find local xpcshell test directory"
|
|
|
|
sys.exit(1)
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
if options.setup:
|
|
|
|
self.setupUtilities()
|
2012-11-14 03:37:53 +04:00
|
|
|
self.setupModules()
|
2011-08-22 12:00:50 +04:00
|
|
|
self.setupTestDir()
|
2012-07-17 20:56:26 +04:00
|
|
|
if options.localAPK:
|
|
|
|
self.remoteAPK = self.remoteJoin(self.remoteBinDir, os.path.basename(options.localAPK))
|
|
|
|
self.setAppRoot()
|
2012-01-08 03:41:08 +04:00
|
|
|
|
|
|
|
def setAppRoot(self):
|
2012-07-17 20:56:26 +04:00
|
|
|
# Determine the application root directory associated with the package
|
2012-01-08 03:41:08 +04:00
|
|
|
# name used by the Fennec APK.
|
|
|
|
self.appRoot = None
|
|
|
|
packageName = None
|
|
|
|
if self.options.localAPK:
|
|
|
|
try:
|
|
|
|
packageName = subprocess.check_output(["unzip", "-p", self.options.localAPK, "package-name.txt"])
|
|
|
|
if packageName:
|
|
|
|
self.appRoot = self.device.getAppRoot(packageName.strip())
|
|
|
|
except Exception as detail:
|
|
|
|
print "unable to determine app root: " + detail
|
|
|
|
pass
|
|
|
|
return None
|
2011-08-22 12:00:50 +04:00
|
|
|
|
|
|
|
def remoteJoin(self, path1, path2):
|
|
|
|
joined = os.path.join(path1, path2)
|
|
|
|
joined = joined.replace('\\', '/')
|
|
|
|
return joined
|
|
|
|
|
|
|
|
def remoteForLocal(self, local):
|
|
|
|
for mapping in self.pathMapping:
|
|
|
|
if (os.path.abspath(mapping.local) == os.path.abspath(local)):
|
|
|
|
return mapping.remote
|
|
|
|
return local
|
|
|
|
|
|
|
|
def setupUtilities(self):
|
|
|
|
remotePrefDir = self.remoteJoin(self.remoteBinDir, "defaults/pref")
|
2012-05-03 14:22:33 +04:00
|
|
|
if (self.device.dirExists(self.remoteTmpDir)):
|
|
|
|
self.device.removeDir(self.remoteTmpDir)
|
|
|
|
self.device.mkDir(self.remoteTmpDir)
|
2011-08-22 12:00:50 +04:00
|
|
|
if (not self.device.dirExists(remotePrefDir)):
|
|
|
|
self.device.mkDirs(self.remoteJoin(remotePrefDir, "extra"))
|
|
|
|
if (not self.device.dirExists(self.remoteScriptsDir)):
|
|
|
|
self.device.mkDir(self.remoteScriptsDir)
|
|
|
|
if (not self.device.dirExists(self.remoteComponentsDir)):
|
|
|
|
self.device.mkDir(self.remoteComponentsDir)
|
|
|
|
|
|
|
|
local = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'head.js')
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteScriptsDir, "head.js")
|
|
|
|
self.device.pushFile(local, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
if not self.localBin:
|
|
|
|
self.localBin = os.path.join(self.options.objdir, "dist/bin")
|
|
|
|
if not os.path.exists(self.localBin):
|
|
|
|
self.localBin = os.path.join(self.options.objdir, "bin")
|
|
|
|
if not os.path.exists(self.localBin):
|
|
|
|
print >>sys.stderr, "Error: could not find bin in objdir"
|
|
|
|
sys.exit(1)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
local = os.path.join(self.localBin, "xpcshell")
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteBinDir, "xpcshell")
|
|
|
|
self.device.pushFile(local, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
local = os.path.join(self.localBin, "components/httpd.js")
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteComponentsDir, "httpd.js")
|
|
|
|
self.device.pushFile(local, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
local = os.path.join(self.localBin, "components/httpd.manifest")
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteComponentsDir, "httpd.manifest")
|
|
|
|
self.device.pushFile(local, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
local = os.path.join(self.localBin, "components/test_necko.xpt")
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteComponentsDir, "test_necko.xpt")
|
|
|
|
self.device.pushFile(local, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-11-27 20:04:46 +04:00
|
|
|
if self.options.localAPK:
|
|
|
|
remoteFile = self.remoteJoin(self.remoteBinDir, os.path.basename(self.options.localAPK))
|
|
|
|
self.device.pushFile(self.options.localAPK, remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2012-07-30 23:04:45 +04:00
|
|
|
self.pushLibs()
|
|
|
|
|
|
|
|
def pushLibs(self):
|
2012-11-27 20:04:46 +04:00
|
|
|
if not self.localLib:
|
|
|
|
if self.options.localAPK:
|
|
|
|
self.localLib = os.path.join(self.options.objdir, "dist/fennec")
|
|
|
|
if not os.path.exists(self.localLib):
|
|
|
|
self.localLib = os.path.join(self.options.objdir, "fennec/lib")
|
|
|
|
if not os.path.exists(self.localLib):
|
|
|
|
print >>sys.stderr, "Error: could not find libs in objdir"
|
|
|
|
sys.exit(1)
|
|
|
|
else:
|
|
|
|
self.localLib = os.path.join(self.options.objdir, 'dist/bin')
|
|
|
|
|
|
|
|
for file in os.listdir(self.localLib):
|
2011-08-22 12:00:50 +04:00
|
|
|
if (file.endswith(".so")):
|
2012-07-17 20:56:26 +04:00
|
|
|
print >> sys.stderr, "Pushing %s.." % file
|
|
|
|
if 'libxul' in file:
|
|
|
|
print >> sys.stderr, "This is a big file, it could take a while."
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteBinDir, file)
|
2012-11-27 20:04:46 +04:00
|
|
|
self.device.pushFile(os.path.join(self.localLib, file), remoteFile)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
2011-12-05 16:19:31 +04:00
|
|
|
# Additional libraries may be found in a sub-directory such as "lib/armeabi-v7a"
|
2012-11-27 20:04:46 +04:00
|
|
|
localArmLib = os.path.join(self.localLib, "lib")
|
2011-12-05 16:19:31 +04:00
|
|
|
if os.path.exists(localArmLib):
|
|
|
|
for root, dirs, files in os.walk(localArmLib):
|
|
|
|
for file in files:
|
|
|
|
if (file.endswith(".so")):
|
2012-10-31 01:21:43 +04:00
|
|
|
remoteFile = self.remoteJoin(self.remoteBinDir, file)
|
|
|
|
self.device.pushFile(os.path.join(root, file), remoteFile)
|
2011-12-05 16:19:31 +04:00
|
|
|
|
2012-11-14 03:37:53 +04:00
|
|
|
def setupModules(self):
|
|
|
|
if self.testingModulesDir:
|
|
|
|
self.device.pushDir(self.testingModulesDir, self.remoteModulesDir)
|
2012-06-19 20:14:41 +04:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
def setupTestDir(self):
|
2012-11-29 00:27:04 +04:00
|
|
|
push_attempts = 10
|
|
|
|
for retry in range(1, push_attempts+1):
|
|
|
|
print 'pushing', self.xpcDir, '(attempt %s of %s)' % (retry, push_attempts)
|
|
|
|
try:
|
|
|
|
self.device.pushDir(self.xpcDir, self.remoteScriptsDir)
|
|
|
|
break
|
|
|
|
except DMError:
|
|
|
|
if retry == push_attempts:
|
|
|
|
raise
|
2011-08-22 12:00:50 +04:00
|
|
|
|
|
|
|
def buildTestList(self):
|
|
|
|
xpcshell.XPCShellTests.buildTestList(self)
|
|
|
|
uniqueTestPaths = set([])
|
|
|
|
for test in self.alltests:
|
|
|
|
uniqueTestPaths.add(test['here'])
|
|
|
|
for testdir in uniqueTestPaths:
|
2012-11-27 20:04:46 +04:00
|
|
|
abbrevTestDir = os.path.relpath(testdir, self.xpcDir)
|
2011-08-22 12:00:50 +04:00
|
|
|
remoteScriptDir = self.remoteJoin(self.remoteScriptsDir, abbrevTestDir)
|
|
|
|
self.pathMapping.append(PathMapping(testdir, remoteScriptDir))
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
def buildXpcsCmd(self, testdir):
|
2012-11-14 03:37:53 +04:00
|
|
|
# change base class' paths to remote paths and use base class to build command
|
|
|
|
self.xpcshell = self.remoteJoin(self.remoteBinDir, "xpcw")
|
|
|
|
self.headJSPath = self.remoteJoin(self.remoteScriptsDir, 'head.js')
|
|
|
|
self.httpdJSPath = self.remoteJoin(self.remoteComponentsDir, 'httpd.js')
|
|
|
|
self.httpdManifest = self.remoteJoin(self.remoteComponentsDir, 'httpd.manifest')
|
|
|
|
self.testingModulesDir = self.remoteModulesDir
|
|
|
|
self.testharnessdir = self.remoteScriptsDir
|
|
|
|
xpcshell.XPCShellTests.buildXpcsCmd(self, testdir)
|
|
|
|
# remove "-g <dir> -a <dir>" and add "--greomni <apk>"
|
|
|
|
del(self.xpcsCmd[1:5])
|
2012-09-05 17:42:02 +04:00
|
|
|
if self.options.localAPK:
|
2012-11-14 03:37:53 +04:00
|
|
|
self.xpcsCmd.insert(3, '--greomni')
|
|
|
|
self.xpcsCmd.insert(4, self.remoteAPK)
|
2011-08-22 12:00:50 +04:00
|
|
|
|
|
|
|
if self.remoteDebugger:
|
|
|
|
# for example, "/data/local/gdbserver" "localhost:12345"
|
|
|
|
self.xpcsCmd = [
|
2012-07-17 20:56:26 +04:00
|
|
|
self.remoteDebugger,
|
|
|
|
self.remoteDebuggerArgs,
|
2011-08-22 12:00:50 +04:00
|
|
|
self.xpcsCmd]
|
|
|
|
|
2012-03-29 03:05:22 +04:00
|
|
|
def getHeadAndTailFiles(self, test):
|
|
|
|
"""Override parent method to find files on remote device."""
|
|
|
|
def sanitize_list(s, kind):
|
|
|
|
for f in s.strip().split(' '):
|
|
|
|
f = f.strip()
|
|
|
|
if len(f) < 1:
|
|
|
|
continue
|
|
|
|
|
|
|
|
path = self.remoteJoin(self.remoteHere, f)
|
|
|
|
if not self.device.fileExists(path):
|
|
|
|
raise Exception('%s file does not exist: %s' % ( kind,
|
|
|
|
path))
|
|
|
|
|
|
|
|
yield path
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
self.remoteHere = self.remoteForLocal(test['here'])
|
2012-03-29 03:05:22 +04:00
|
|
|
|
|
|
|
return (list(sanitize_list(test['head'], 'head')),
|
|
|
|
list(sanitize_list(test['tail'], 'tail')))
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
def buildCmdTestFile(self, name):
|
|
|
|
remoteDir = self.remoteForLocal(os.path.dirname(name))
|
|
|
|
if remoteDir == self.remoteHere:
|
|
|
|
remoteName = os.path.basename(name)
|
|
|
|
else:
|
|
|
|
remoteName = self.remoteJoin(remoteDir, os.path.basename(name))
|
|
|
|
return ['-e', 'const _TEST_FILE = ["%s"];' %
|
|
|
|
replaceBackSlashes(remoteName)]
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
def setupProfileDir(self):
|
2010-03-16 01:29:27 +03:00
|
|
|
self.device.removeDir(self.profileDir)
|
|
|
|
self.device.mkDir(self.profileDir)
|
2011-08-22 12:00:50 +04:00
|
|
|
if self.interactive or self.singleFile:
|
|
|
|
self.log.info("TEST-INFO | profile dir is %s" % self.profileDir)
|
2010-03-16 01:29:27 +03:00
|
|
|
return self.profileDir
|
2010-03-13 21:57:06 +03:00
|
|
|
|
2012-11-06 15:43:58 +04:00
|
|
|
def logCommand(self, name, completeCmd, testdir):
|
|
|
|
self.log.info("TEST-INFO | %s | full command: %r" % (name, completeCmd))
|
|
|
|
self.log.info("TEST-INFO | %s | current directory: %r" % (name, self.remoteHere))
|
|
|
|
self.log.info("TEST-INFO | %s | environment: %s" % (name, self.env))
|
|
|
|
|
|
|
|
def setupLeakLogging(self):
|
2012-11-14 03:37:56 +04:00
|
|
|
self.env["XPCOM_MEM_LEAK_LOG"] = self.remoteJoin(self.profileDir, "leaks.log")
|
|
|
|
return self.env["XPCOM_MEM_LEAK_LOG"]
|
2012-11-06 15:43:58 +04:00
|
|
|
|
2012-07-30 23:04:45 +04:00
|
|
|
def setLD_LIBRARY_PATH(self, env):
|
|
|
|
env["LD_LIBRARY_PATH"]=self.remoteBinDir
|
|
|
|
|
2012-11-14 03:37:51 +04:00
|
|
|
def pushWrapper(self):
|
|
|
|
# Rather than executing xpcshell directly, this wrapper script is
|
|
|
|
# used. By setting environment variables and the cwd in the script,
|
|
|
|
# the length of the per-test command line is shortened. This is
|
|
|
|
# often important when using ADB, as there is a limit to the length
|
|
|
|
# of the ADB command line.
|
|
|
|
localWrapper = tempfile.mktemp()
|
|
|
|
f = open(localWrapper, "w")
|
|
|
|
f.write("#!/system/bin/sh\n")
|
|
|
|
for envkey, envval in self.env.iteritems():
|
|
|
|
f.write("export %s=%s\n" % (envkey, envval))
|
|
|
|
f.write("cd $1\n")
|
|
|
|
f.write("echo xpcw: cd $1\n")
|
|
|
|
f.write("shift\n")
|
|
|
|
f.write("echo xpcw: xpcshell \"$@\"\n")
|
|
|
|
f.write("%s/xpcshell \"$@\"\n" % self.remoteBinDir)
|
|
|
|
f.close()
|
|
|
|
remoteWrapper = self.remoteJoin(self.remoteBinDir, "xpcw")
|
|
|
|
self.device.pushFile(localWrapper, remoteWrapper)
|
|
|
|
os.remove(localWrapper)
|
|
|
|
self.device.chmodDir(self.remoteBinDir)
|
|
|
|
|
2012-11-06 15:43:58 +04:00
|
|
|
def buildEnvironment(self):
|
|
|
|
self.env = {}
|
2012-11-14 03:37:56 +04:00
|
|
|
self.buildCoreEnvironment()
|
2012-11-06 15:43:58 +04:00
|
|
|
self.setLD_LIBRARY_PATH(self.env)
|
|
|
|
self.env["MOZ_LINKER_CACHE"]=self.remoteBinDir
|
|
|
|
if self.options.localAPK and self.appRoot:
|
|
|
|
self.env["GRE_HOME"]=self.appRoot
|
|
|
|
self.env["XPCSHELL_TEST_PROFILE_DIR"]=self.profileDir
|
|
|
|
self.env["TMPDIR"]=self.remoteTmpDir
|
|
|
|
self.env["HOME"]=self.profileDir
|
2012-11-16 18:43:55 +04:00
|
|
|
if self.options.setup:
|
|
|
|
self.pushWrapper()
|
2012-11-06 15:43:58 +04:00
|
|
|
|
2010-03-13 21:57:06 +03:00
|
|
|
def launchProcess(self, cmd, stdout, stderr, env, cwd):
|
2012-11-14 03:37:51 +04:00
|
|
|
cmd.insert(1, self.remoteHere)
|
2012-02-28 21:20:56 +04:00
|
|
|
outputFile = "xpcshelloutput"
|
|
|
|
f = open(outputFile, "w+")
|
2012-11-14 03:37:51 +04:00
|
|
|
self.shellReturnCode = self.device.shell(cmd, f)
|
2012-02-28 21:20:56 +04:00
|
|
|
f.close()
|
2012-07-17 20:56:26 +04:00
|
|
|
# The device manager may have timed out waiting for xpcshell.
|
2012-02-28 21:20:56 +04:00
|
|
|
# Guard against an accumulation of hung processes by killing
|
|
|
|
# them here. Note also that IPC tests may spawn new instances
|
|
|
|
# of xpcshell.
|
2012-10-08 00:21:30 +04:00
|
|
|
self.device.killProcess(cmd[0])
|
|
|
|
self.device.killProcess("xpcshell")
|
2012-02-28 21:20:56 +04:00
|
|
|
return outputFile
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
def communicate(self, proc):
|
2012-02-28 21:20:56 +04:00
|
|
|
f = open(proc, "r")
|
|
|
|
contents = f.read()
|
|
|
|
f.close()
|
|
|
|
os.remove(proc)
|
|
|
|
return contents, ""
|
|
|
|
|
2012-10-08 00:21:30 +04:00
|
|
|
def poll(self, proc):
|
|
|
|
if self.device.processExist("xpcshell") is None:
|
|
|
|
return self.getReturnCode(proc)
|
|
|
|
# Process is still running
|
|
|
|
return None
|
|
|
|
|
|
|
|
def kill(self, proc):
|
|
|
|
return self.device.killProcess("xpcshell", True)
|
|
|
|
|
2012-02-28 21:20:56 +04:00
|
|
|
def getReturnCode(self, proc):
|
|
|
|
if self.shellReturnCode is not None:
|
2012-05-23 18:26:07 +04:00
|
|
|
return self.shellReturnCode
|
2012-02-28 21:20:56 +04:00
|
|
|
else:
|
|
|
|
return -1
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
def removeDir(self, dirname):
|
|
|
|
self.device.removeDir(dirname)
|
|
|
|
|
|
|
|
#TODO: consider creating a separate log dir. We don't have the test file structure,
|
|
|
|
# so we use filename.log. Would rather see ./logs/filename.log
|
2011-08-22 12:00:50 +04:00
|
|
|
def createLogFile(self, test, stdout, leakLogs):
|
2010-03-13 21:57:06 +03:00
|
|
|
try:
|
|
|
|
f = None
|
|
|
|
filename = test.replace('\\', '/').split('/')[-1] + ".log"
|
|
|
|
f = open(filename, "w")
|
|
|
|
f.write(stdout)
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
for leakLog in leakLogs:
|
|
|
|
if os.path.exists(leakLog):
|
|
|
|
leaks = open(leakLog, "r")
|
2010-03-13 21:57:06 +03:00
|
|
|
f.write(leaks.read())
|
|
|
|
leaks.close()
|
|
|
|
finally:
|
|
|
|
if f <> None:
|
|
|
|
f.close()
|
|
|
|
|
|
|
|
class RemoteXPCShellOptions(xpcshell.XPCShellOptions):
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
def __init__(self):
|
|
|
|
xpcshell.XPCShellOptions.__init__(self)
|
|
|
|
defaults = {}
|
|
|
|
|
|
|
|
self.add_option("--deviceIP", action="store",
|
|
|
|
type = "string", dest = "deviceIP",
|
|
|
|
help = "ip address of remote device to test")
|
|
|
|
defaults["deviceIP"] = None
|
2012-07-17 20:56:26 +04:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
self.add_option("--devicePort", action="store",
|
|
|
|
type = "string", dest = "devicePort",
|
|
|
|
help = "port of remote device to test")
|
|
|
|
defaults["devicePort"] = 20701
|
|
|
|
|
|
|
|
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"
|
2012-07-17 20:56:26 +04:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
self.add_option("--objdir", action="store",
|
|
|
|
type = "string", dest = "objdir",
|
|
|
|
help = "local objdir, containing xpcshell binaries")
|
|
|
|
defaults["objdir"] = None
|
2012-07-17 20:56:26 +04:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
self.add_option("--apk", action="store",
|
|
|
|
type = "string", dest = "localAPK",
|
|
|
|
help = "local path to Fennec APK")
|
|
|
|
defaults["localAPK"] = None
|
|
|
|
|
|
|
|
self.add_option("--noSetup", action="store_false",
|
|
|
|
dest = "setup",
|
|
|
|
help = "do not copy any files to device (to be used only if device is already setup)")
|
|
|
|
defaults["setup"] = True
|
|
|
|
|
|
|
|
self.set_defaults(**defaults)
|
|
|
|
|
|
|
|
class PathMapping:
|
|
|
|
|
|
|
|
def __init__(self, localDir, remoteDir):
|
|
|
|
self.local = localDir
|
|
|
|
self.remote = remoteDir
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
def main():
|
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
parser = RemoteXPCShellOptions()
|
|
|
|
options, args = parser.parse_args()
|
|
|
|
|
|
|
|
if len(args) < 1 and options.manifest is None:
|
|
|
|
print >>sys.stderr, """Usage: %s <test dirs>
|
|
|
|
or: %s --manifest=test.manifest """ % (sys.argv[0], sys.argv[0])
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if (options.dm_trans == "adb"):
|
|
|
|
if (options.deviceIP):
|
|
|
|
dm = devicemanagerADB.DeviceManagerADB(options.deviceIP, options.devicePort)
|
|
|
|
else:
|
2012-03-17 02:36:28 +04:00
|
|
|
dm = devicemanagerADB.DeviceManagerADB()
|
2011-08-22 12:00:50 +04:00
|
|
|
else:
|
|
|
|
dm = devicemanagerSUT.DeviceManagerSUT(options.deviceIP, options.devicePort)
|
|
|
|
if (options.deviceIP == None):
|
|
|
|
print "Error: you must provide a device IP to connect to via the --device option"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if options.interactive and not options.testPath:
|
|
|
|
print >>sys.stderr, "Error: You must specify a test filename in interactive mode!"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if not options.objdir:
|
|
|
|
print >>sys.stderr, "Error: You must specify an objdir"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
if not options.localAPK:
|
|
|
|
for file in os.listdir(os.path.join(options.objdir, "dist")):
|
|
|
|
if (file.endswith(".apk") and file.startswith("fennec")):
|
|
|
|
options.localAPK = os.path.join(options.objdir, "dist")
|
|
|
|
options.localAPK = os.path.join(options.localAPK, file)
|
|
|
|
print >>sys.stderr, "using APK: " + options.localAPK
|
|
|
|
break
|
2012-07-17 20:56:26 +04:00
|
|
|
|
2011-08-22 12:00:50 +04:00
|
|
|
if not options.localAPK:
|
|
|
|
print >>sys.stderr, "Error: please specify an APK"
|
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
xpcsh = XPCShellRemote(dm, options, args)
|
|
|
|
|
2012-07-17 20:56:26 +04:00
|
|
|
if not xpcsh.runTests(xpcshell='xpcshell',
|
|
|
|
testdirs=args[0:],
|
2011-08-22 12:00:50 +04:00
|
|
|
**options.__dict__):
|
|
|
|
sys.exit(1)
|
|
|
|
|
2010-03-13 21:57:06 +03:00
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
main()
|
|
|
|
|