author | William Lachance <wlachance@mozilla.com> |
Mon, 05 Nov 2012 15:18:54 -0800 | |
changeset 112358 | 613bfe02f0c1096027e73238a9fcc27ee480531e |
parent 112357 | 4cee05d5b1ce84770ad35222f7962289c323304f |
child 112359 | c697c428739d1014d81e7e8b0afe8b28f5a08642 |
push id | 23812 |
push user | emorley@mozilla.com |
push date | Tue, 06 Nov 2012 14:01:34 +0000 |
treeherder | mozilla-central@f4aeed115e54 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jmaher |
bugs | 808719 |
milestone | 19.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 @@ -28,16 +28,18 @@ def abstractmethod(method): def not_implemented(*args, **kwargs): raise NotImplementedError('Abstract method %s at File "%s", line %s ' 'should be implemented by a concrete class' % (repr(method), filename, line)) return not_implemented class DeviceManager: + logcatNeedsRoot = True + @abstractmethod def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ Executes shell command on device and returns exit code cmd - Command string to execute outputfile - File to store output env - Environment to pass to exec command @@ -211,23 +213,19 @@ class DeviceManager: Returns contents of remoteFile using the "pull" command. returns: success: output of pullfile, string failure: None """ @abstractmethod - def getFile(self, remoteFile, localFile = ''): + def getFile(self, remoteFile, localFile): """ Copy file from device (remoteFile) to host (localFile) - - returns: - success: contents of file, string - failure: None """ @abstractmethod def getDirectory(self, remoteDir, localDir, checkDir=True): """ Copy directory structure from device (remoteDir) to host (localDir) returns: @@ -486,32 +484,34 @@ class DeviceManager: def recordLogcat(self): """ Clears the logcat file making it easier to view specific events """ #TODO: spawn this off in a separate thread/process so we can collect all the logcat information # Right now this is just clearing the logcat so we can only see what happens after this call. - buf = StringIO.StringIO() - self.shell(['/system/bin/logcat', '-c'], buf, root=True) - - def getLogcat(self): - """ - Returns the contents of the logcat file as a string + self.shellCheckOutput(['/system/bin/logcat', '-c'], root=self.logcatNeedsRoot) - returns: - success: contents of logcat, string - failure: None + def getLogcat(self, filterSpecs=["dalvikvm:S", "ConnectivityService:S", + "WifiMonitor:S", "WifiStateTracker:S", + "wpa_supplicant:S", "NetworkStateTracker:S"], + format="time", + filterOutRegexps=[]): + """ + Returns the contents of the logcat file as a list of strings """ - buf = StringIO.StringIO() - if self.shell(["/system/bin/logcat", "-d", "dalvikvm:S", "ConnectivityService:S", "WifiMonitor:S", "WifiStateTracker:S", "wpa_supplicant:S", "NetworkStateTracker:S"], buf, root=True) != 0: - return None + cmdline = ["/system/bin/logcat", "-v", format, "-d"] + filterSpecs + lines = self.shellCheckOutput(cmdline, + root=self.logcatNeedsRoot).split('\r') - return str(buf.getvalue()[0:-1]).rstrip().split('\r') + for regex in filterOutRegexps: + lines = [line for line in lines if not re.search(regex, line)] + + return lines @staticmethod def _writePNG(buf, width, height): """ Method for writing a PNG from a buffer, used by getScreenshot on older devices Based on: http://code.activestate.com/recipes/577443-write-a-png-image-in-native-python/ """ width_byte_4 = width * 4
--- a/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerADB.py @@ -18,20 +18,22 @@ class DeviceManagerADB(DeviceManager): self.retrylimit = retrylimit self.retries = 0 self._sock = None self.haveRootShell = False self.haveSu = False self.useRunAs = False self.useDDCopy = False self.useZip = False + self.logcatNeedsRoot = False self.packageName = None self.tempDir = None self.deviceRoot = deviceRoot self.default_timeout = 300 + self.pollingInterval = 0.01 # the path to adb, or 'adb' to assume that it's on the PATH self.adbPath = adbPath # The serial number of the device to use with adb, used in cases # where multiple devices are being managed by the same adb instance. self.deviceSerial = deviceSerial @@ -126,17 +128,17 @@ class DeviceManagerADB(DeviceManager): 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(1) + 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')) lastline = _pop_last_line(outputfile) @@ -266,24 +268,17 @@ class DeviceManagerADB(DeviceManager): """ return self._runCmd(["shell", "rmdir", remoteDir]).stdout.read() def removeDir(self, remoteDir): """ Does a recursive delete of directory on the device: rm -Rf remoteDir """ if (self.dirExists(remoteDir)): - files = self.listFiles(remoteDir.strip()) - for f in files: - path = remoteDir.strip() + "/" + f.strip() - if self.dirExists(path): - self.removeDir(path) - else: - self.removeFile(path) - self._removeSingleDir(remoteDir.strip()) + self._runCmd(["shell", "rm", "-r", remoteDir]) else: self.removeFile(remoteDir.strip()) def listFiles(self, rootdir): """ Lists files on the device rootdir returns array of filenames, ['file1', 'file2', ...] @@ -391,17 +386,17 @@ class DeviceManagerADB(DeviceManager): If forceKill is True, process is killed regardless of state """ procs = self.getProcessList() for (pid, name, user) in procs: if name == appname: args = ["shell", "kill"] if forceKill: args.append("-9") - args.append(pid) + args.append(str(pid)) p = self._runCmdAs(args) p.communicate() if p.returncode != 0: raise DMError("Error killing process " "'%s': %s" % (appname, p.stdout.read())) def catFile(self, remoteFile): """ @@ -445,25 +440,21 @@ class DeviceManagerADB(DeviceManager): self._runPull(remoteFile, localFile) f = open(localFile, 'r') ret = f.read() f.close() os.remove(localFile) return ret - def getFile(self, remoteFile, localFile = 'temp.txt'): + def getFile(self, remoteFile, localFile): """ Copy file from device (remoteFile) to host (localFile). """ - contents = self.pullFile(remoteFile) - - fhandle = open(localFile, 'wb') - fhandle.write(contents) - fhandle.close() + self._runPull(remoteFile, localFile) def getDirectory(self, remoteDir, localDir, checkDir=True): """ Copy directory structure from device (remoteDir) to host (localDir) """ self._runCmd(["pull", remoteDir, localDir]) def validateFile(self, remoteFile, localFile): @@ -607,45 +598,16 @@ class DeviceManagerADB(DeviceManager): """ Returns device time in milliseconds since the epoch """ timestr = self._runCmd(["shell", "date", "+%s"]).stdout.read().strip() if (not timestr or not timestr.isdigit()): raise DMError("Unable to get current time using date (got: '%s')" % timestr) return str(int(timestr)*1000) - def recordLogcat(self): - """ - Clears the logcat file making it easier to view specific events - """ - # this does not require root privileges with ADB - try: - self.shellCheckOutput(['/system/bin/logcat', '-c']) - except DMError, e: - print "DeviceManager: Error recording logcat '%s'" % e.msg - # to preserve compat with parent method, just ignore exceptions - pass - - def getLogcat(self): - """ - Returns the contents of the logcat file as a string - - returns: - success: contents of logcat, string - failure: None - """ - # this does not require root privileges with ADB - try: - output = self.shellCheckOutput(["/system/bin/logcat", "-d", "dalvikvm:S", "ConnectivityService:S", "WifiMonitor:S", "WifiStateTracker:S", "wpa_supplicant:S", "NetworkStateTracker:S"]) - return output.split('\r') - except DMError, e: - # to preserve compat with parent method, just ignore exceptions - print "DeviceManager: Error recording logcat '%s'" % e.msg - pass - def getInfo(self, directive=None): """ Returns information about the device Directive indicates the information you want to get, your choices are: os - name of the os id - unique id of the device uptime - uptime of the device @@ -757,17 +719,17 @@ class DeviceManagerADB(DeviceManager): # We are asserting that all commands will complete in this time unless otherwise specified timeout = self.default_timeout timeout = int(timeout) proc = subprocess.Popen(finalArgs) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: - time.sleep(1) + time.sleep(self.pollingInterval) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for _checkCmd call") return ret_code def _checkCmdAs(self, args, timeout=None): """
--- a/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py +++ b/testing/mozbase/mozdevice/mozdevice/devicemanagerSUT.py @@ -13,17 +13,16 @@ import subprocess from threading import Thread import StringIO from devicemanager import DeviceManager, DMError, NetworkTools, _pop_last_line import errno from distutils.version import StrictVersion class DeviceManagerSUT(DeviceManager): debug = 2 - tempRoot = os.getcwd() base_prompt = '$>' base_prompt_re = '\$\>' prompt_sep = '\x00' prompt_regex = '.*(' + base_prompt_re + prompt_sep + ')' agentErrorRE = re.compile('^##AGENT-WARNING##\ ?(.*)') default_timeout = 300 def __init__(self, host, port = 20701, retrylimit = 5, deviceRoot = None, **kwargs): @@ -636,23 +635,20 @@ class DeviceManagerSUT(DeviceManager): # read file data total_to_recv = filesize + len(prompt) buf = read_exact(total_to_recv, buf, 'could not get all file data') if buf[-len(prompt):] != prompt: err('no prompt found after file data--DeviceManager may be out of sync with agent') return buf return buf[:-len(prompt)] - def getFile(self, remoteFile, localFile = ''): + def getFile(self, remoteFile, localFile): """ Copy file from device (remoteFile) to host (localFile) """ - if localFile == '': - localFile = os.path.join(self.tempRoot, "temp.txt") - data = self.pullFile(remoteFile) fhandle = open(localFile, 'wb') fhandle.write(data) fhandle.close() if not self.validateFile(remoteFile, localFile): raise DMError("Automation Error: Failed to validate file when downloading %s" % remoteFile)
--- 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.12' +PACKAGE_VERSION = '0.14' # 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 = ''