author | William Lachance <wlachance@mozilla.com> |
Wed, 05 Dec 2012 12:17:38 -0500 | |
changeset 115104 | 5488aa7e3fc3855cb481addac7e8f9532e277d72 |
parent 115103 | 51cbdd0f1ba456f204acb55eee400bb0a008e108 |
child 115105 | 61b7d462bc9e49130dd16f442f8d31930cc68dc8 |
push id | 23973 |
push user | emorley@mozilla.com |
push date | Thu, 06 Dec 2012 10:04:18 +0000 |
treeherder | mozilla-central@ddda5400c826 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | ahal |
bugs | 818080 |
milestone | 20.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/testing/mozbase/mozdevice/mozdevice/devicemanager.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanager.py @@ -57,17 +57,17 @@ class DeviceManager: timeout - specified in seconds, defaults to 'default_timeout' root - Specifies whether command requires root privileges """ buf = StringIO.StringIO() retval = self.shell(cmd, buf, env=env, cwd=cwd, timeout=timeout, root=root) output = str(buf.getvalue()[0:-1]).rstrip() buf.close() if retval != 0: - raise DMError("Non-zero return code for command: %s (output: '%s', retval: '%i')" % (cmd, output, retval)) + raise DMError("Non-zero return code for command: %s (output: '%s', retval: '%s')" % (cmd, output, retval)) return output @abstractmethod def pushFile(self, localname, destname): """ Copies localname from the host to destname on the device """ @@ -77,24 +77,26 @@ class DeviceManager: Creates a single directory on the device file system """ def mkDirs(self, filename): """ Make directory structure on the device WARNING: does not create last part of the path """ - parts = filename.split('/') - name = "" - for part in parts: - if (part == parts[-1]): - break - if (part != ""): - name += '/' + part - self.mkDir(name) # mkDir will check previous existence + dirParts = filename.rsplit('/', 1) + if not self.dirExists(dirParts[0]): + parts = filename.split('/') + name = "" + for part in parts: + if part == parts[-1]: + break + if part != "": + name += '/' + part + self.mkDir(name) # mkDir will check previous existence @abstractmethod def pushDir(self, localDir, remoteDir): """ Push localDir from host to remoteDir on the device """ @abstractmethod
--- a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py @@ -118,33 +118,39 @@ class DeviceManagerADB(DeviceManager): envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args=[self._adbPath] if self._deviceSerial: args.extend(['-s', self._deviceSerial]) args.extend(["shell", cmdline]) - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + procOut = tempfile.SpooledTemporaryFile() + procErr = tempfile.SpooledTemporaryFile() + proc = subprocess.Popen(args, stdout=procOut, stderr=procErr) if not timeout: # We are asserting that all commands will complete in this time unless otherwise specified timeout = self.default_timeout timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(self._pollingInterval) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") - (stdout, stderr) = proc.communicate() - outputfile.write(stdout.rstrip('\n')) + + procOut.seek(0) + outputfile.write(procOut.read().rstrip('\n')) + procOut.close() + procErr.close() lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code
--- a/testing/mozbase/mozdevice/mozdevice/dmcli.py +++ b/testing/mozbase/mozdevice/mozdevice/dmcli.py @@ -1,27 +1,30 @@ # 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/. """ Command-line client to control a device """ +import errno import os import posixpath import StringIO import sys import textwrap import mozdevice from optparse import OptionParser class DMCli(object): - def __init__(self, args=sys.argv[1:]): + def __init__(self): + # a value of None for 'max_args' means there is no limit to the number + # of arguments. 'min_args' should always have an integer value >= 0. self.commands = { 'install': { 'function': self.install, 'min_args': 1, 'max_args': 1, 'help_args': '<file>', 'help': 'push this package file to the device and install it' }, 'killapp': { 'function': self.killapp, 'min_args': 1, 'max_args': 1, @@ -43,41 +46,59 @@ class DMCli(object): 'help_args': '<local> [remote]', 'help': 'copy file/dir from device' }, 'shell': { 'function': self.shell, 'min_args': 1, 'max_args': None, 'help_args': '<command>', 'help': 'run shell command on device' }, 'info': { 'function': self.getinfo, - 'min_args': None, + 'min_args': 0, 'max_args': 1, 'help_args': '[os|id|uptime|systime|screen|memory|processes]', 'help': 'get information on a specified ' 'aspect of the device (if no argument ' 'given, print all available information)' }, 'ps': { 'function': self.processlist, - 'min_args': None, + 'min_args': 0, 'max_args': 0, 'help_args': '', 'help': 'get information on running processes on device' }, + 'logcat' : { 'function': self.logcat, + 'min_args': 0, + 'max_args': 0, + 'help_args': '', + 'help': 'get logcat from device' + }, 'ls': { 'function': self.listfiles, 'min_args': 1, 'max_args': 1, 'help_args': '<remote>', 'help': 'list files on device' }, 'rm': { 'function': lambda f: self.dm.removeFile(f), 'min_args': 1, 'max_args': 1, 'help_args': '<remote>', 'help': 'remove file from device' }, + 'isdir': { 'function': self.isdir, + 'min_args': 1, + 'max_args': 1, + 'help_args': '<remote>', + 'help': 'print if remote file is a directory' + }, + 'mkdir': { 'function': lambda d: self.dm.mkDir(d), + 'min_args': 1, + 'max_args': 1, + 'help_args': '<remote>', + 'help': 'makes a directory on device' + }, 'rmdir': { 'function': lambda d: self.dm.removeDir(d), 'min_args': 1, 'max_args': 1, 'help_args': '<remote>', 'help': 'recursively remove directory from device' }, 'screencap': { 'function': lambda f: self.dm.saveScreenshot(f), 'min_args': 1, @@ -95,41 +116,48 @@ class DMCli(object): initial_indent=" ", subsequent_indent=" ") for (cmdname, cmd) in sorted(self.commands.iteritems())]) self.parser = OptionParser(usage) self.add_options(self.parser) + + def run(self, args=sys.argv[1:]): (self.options, self.args) = self.parser.parse_args(args) if len(self.args) < 1: self.parser.error("must specify command") if self.options.dmtype == "sut" and not self.options.host and \ not self.options.hwid: self.parser.error("Must specify device ip in TEST_DEVICE or " "with --host option with SUT") (command_name, command_args) = (self.args[0], self.args[1:]) if command_name not in self.commands: self.parser.error("Invalid command. Valid commands: %s" % " ".join(self.commands.keys())) command = self.commands[command_name] - if command['min_args'] and len(command_args) < command['min_args'] or \ - command['max_args'] and len(command_args) > command['max_args']: + if (len(command_args) < command['min_args'] or + (command['max_args'] is not None and len(command_args) > + command['max_args'])): self.parser.error("Wrong number of arguments") self.dm = self.getDevice(dmtype=self.options.dmtype, hwid=self.options.hwid, host=self.options.host, port=self.options.port) - command['function'](*command_args) + ret = command['function'](*command_args) + if ret is None: + ret = 0 + + sys.exit(ret) def add_options(self, parser): parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="Verbose output from DeviceManager", default=False) parser.add_option("--host", action="store", type="string", dest="host", @@ -227,24 +255,36 @@ class DMCli(object): elif not directive and not infoitem: print "%s:" % infokey.upper() elif not directive: for line in infoitem: print "%s: %s" % (infokey.upper(), line) else: print "%s" % "\n".join(infoitem) + def logcat(self): + print ''.join(self.dm.getLogcat()) + def processlist(self): pslist = self.dm.getProcessList() for ps in pslist: print " ".join(str(i) for i in ps) def listfiles(self, dir): filelist = self.dm.listFiles(dir) for file in filelist: print file + def isdir(self, file): + if self.dm.dirExists(file): + print "TRUE" + return 0 + + print "FALSE" + return errno.ENOTDIR + def cli(args=sys.argv[1:]): # process the command line - cli = DMCli(args) + cli = DMCli() + cli.run(args) if __name__ == '__main__': cli()
--- a/testing/mozbase/mozdevice/setup.py +++ b/testing/mozbase/mozdevice/setup.py @@ -1,16 +1,16 @@ # 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/. import os from setuptools import setup -PACKAGE_VERSION = '0.15' +PACKAGE_VERSION = '0.16' # take description from README here = os.path.dirname(os.path.abspath(__file__)) try: description = file(os.path.join(here, 'README.md')).read() except (OSError, IOError): description = ''