Bug 797144 - mirror mozbase -> m-c for bug 796863 @ db7f115a9e;r=wlach

This commit is contained in:
Jeff Hammel 2012-10-03 09:13:21 -07:00
parent 2e41e62ebd
commit 626816e3a2
5 changed files with 242 additions and 3 deletions

View File

@ -0,0 +1,5 @@
# 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/.
from b2gmixin import DeviceADB, DeviceSUT

View File

@ -0,0 +1,171 @@
# 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/.
from __future__ import with_statement
import datetime
import os
import re
import tempfile
import time
import shutil
import socket
import subprocess
from marionette import Marionette
from mozdevice import DeviceManagerADB, DeviceManagerSUT, DMError
class B2GMixin(object):
profileDir = None
userJS = "/data/local/user.js"
marionette = None
def __init__(self, host=None, marionette_port=2828, **kwargs):
self.marionetteHost = host
self.marionettePort = marionette_port
def cleanup(self):
if self.profileDir:
self.restoreProfile()
def waitForPort(self, timeout):
"""
Wait for the marionette server to respond.
Timeout parameter is in seconds
"""
print "waiting for port"
starttime = datetime.datetime.now()
while datetime.datetime.now() - starttime < datetime.timedelta(seconds=timeout):
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print "trying %s %s" % (self.marionettePort, self.marionetteHost)
sock.connect((self.marionetteHost, self.marionettePort))
data = sock.recv(16)
sock.close()
if '"from"' in data:
return True
except socket.error:
pass
except Exception as e:
raise DMError("Could not connect to marionette: %s" % e)
time.sleep(1)
raise DMError("Could not communicate with Marionette port")
def setupMarionette(self):
"""
Start a marionette session.
If no host is given, then this will get the ip
of the device, and set up networking if needed.
"""
if not self.marionetteHost:
self.setupDHCP()
self.marionetteHost = self.getIP()
if not self.marionette:
self.marionette = Marionette(self.marionetteHost, self.marionettePort)
if not self.marionette.session:
self.waitForPort(30)
self.marionette.start_session()
def restartB2G(self):
"""
Restarts the b2g process on the device
"""
#restart b2g so we start with a clean slate
if self.marionette and self.marionette.session:
self.marionette.delete_session()
self.shellCheckOutput(['stop', 'b2g'])
# Wait for a bit to make sure B2G has completely shut down.
tries = 10
while "b2g" in self.shellCheckOutput(['ps', 'b2g']) and tries > 0:
tries -= 1
time.sleep(1)
if tries == 0:
raise DMError("Could not kill b2g process")
self.shellCheckOutput(['start', 'b2g'])
def setupProfile(self, prefs=None):
"""
Sets up the user profile on the device,
The 'prefs' is a string of user_prefs to add to the profile.
If it is not set, it will default to a standard b2g testing profile.
"""
if not prefs:
prefs = """
user_pref("power.screen.timeout", 999999);
user_pref("devtools.debugger.force-local", false);
"""
#remove previous user.js if there is one
if not self.profileDir:
self.profileDir = tempfile.mkdtemp()
our_userJS = os.path.join(self.profileDir, "user.js")
if os.path.exists(our_userJS):
os.remove(our_userJS)
#copy profile
try:
output = self.getFile(self.userJS, our_userJS)
except subprocess.CalledProcessError:
pass
#if we successfully copied the profile, make a backup of the file
if os.path.exists(our_userJS):
self.shellCheckOutput(['dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
with open(our_userJS, 'a') as user_file:
user_file.write("%s" % prefs)
self.pushFile(our_userJS, self.userJS)
self.restartB2G()
self.setupMarionette()
def setupDHCP(self, conn_type='eth0'):
"""
Sets up networking.
If conn_type is not set, it will assume eth0.
"""
tries = 5
while tries > 0:
print "attempts left: %d" % tries
try:
self.shellCheckOutput(['netcfg', conn_type, 'dhcp'], timeout=10)
if self.getIP():
return
except DMError:
pass
tries = tries - 1
raise DMError("Could not set up network connection")
def restoreProfile(self):
"""
Restores the original profile
"""
if not self.profileDir:
raise DMError("There is no profile to restore")
#if we successfully copied the profile, make a backup of the file
our_userJS = os.path.join(self.profileDir, "user.js")
if os.path.exists(our_userJS):
self.shellCheckOutput(['dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
shutil.rmtree(self.profileDir)
self.profileDir = None
def getAppInfo(self):
"""
Returns the appinfo, with an additional "date" key.
"""
if not self.marionette or not self.marionette.session:
self.setupMarionette()
self.marionette.set_context("chrome")
appinfo = self.marionette.execute_script("""
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
return appInfo;
""")
(year, month, day) = (appinfo["appBuildID"][0:4], appinfo["appBuildID"][4:6], appinfo["appBuildID"][6:8])
appinfo['date'] = "%s-%s-%s" % (year, month, day)
return appinfo
class DeviceADB(DeviceManagerADB, B2GMixin):
def __init__(self, **kwargs):
DeviceManagerADB.__init__(self, **kwargs)
B2GMixin.__init__(self, **kwargs)
class DeviceSUT(DeviceManagerSUT, B2GMixin):
def __init__(self, **kwargs):
DeviceManagerSUT.__init__(self, **kwargs)
B2GMixin.__init__(self, **kwargs)

View File

@ -0,0 +1,33 @@
# 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.1'
# 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 = ''
deps = ['mozdevice', 'marionette_client']
setup(name='mozb2g',
version=PACKAGE_VERSION,
description="B2G specific code for device automation",
long_description=description,
classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
keywords='',
author='Mozilla Automation and Testing Team',
author_email='tools@lists.mozilla.org',
url='https://wiki.mozilla.org/Auto-tools/Projects/MozBase',
license='MPL',
packages=['mozb2g'],
include_package_data=True,
zip_safe=False,
install_requires=deps
)

View File

@ -762,6 +762,35 @@ class DeviceManagerADB(DeviceManager):
return None
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:

View File

@ -290,7 +290,7 @@ falling back to not using job objects for managing child processes"""
if MOZPROCESS_DEBUG:
print "DBG::MOZPROC Self.pid value is: %s" % self.pid
while True:
msgid = c_ulong(0)
compkey = c_ulong(0)
@ -311,8 +311,9 @@ falling back to not using job objects for managing child processes"""
# don't want to mistake that situation for the situation of an unexpected
# parent abort (which is what we're looking for here).
if diff.seconds > self.MAX_IOCOMPLETION_PORT_NOTIFICATION_DELAY:
print >> sys.stderr, "Parent process exited without \
killing children, attempting to kill children"
print >> sys.stderr, "Parent process %s exited with children alive:" % self.pid
print >> sys.stderr, "PIDS: %s" % ', '.join(self._spawned_procs.keys())
print >> sys.stderr, "Attempting to kill them..."
self.kill()
self._process_events.put({self.pid: 'FINISHED'})