Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2012-08-08 22:48:37 -04:00
commit 0a4c0b6191
2 changed files with 85 additions and 58 deletions

View File

@ -18,8 +18,8 @@ from devicemanager import DeviceManager, NetworkTools
from mozprocess import ProcessHandlerMixin
class LogcatProc(ProcessHandlerMixin):
"""Process handler for logcat which puts all output in a Queue.
class StdOutProc(ProcessHandlerMixin):
"""Process handler for b2g which puts all output in a Queue.
"""
def __init__(self, cmd, queue, **kwargs):
@ -76,6 +76,20 @@ class B2GRemoteAutomation(Automation):
env['MOZ_HIDE_RESULTS_TABLE'] = '1'
return env
def waitForNet(self):
active = False
time_out = 0
while not active and time_out < 40:
data = self._devicemanager.runCmd(['shell', '/system/bin/netcfg']).stdout.readlines()
data.pop(0)
for line in data:
if (re.search(r'UP\s+(?:[0-9]{1,3}\.){3}[0-9]{1,3}', line)):
active = True
break
time_out += 1
time.sleep(1)
return active
def checkForCrashes(self, directory, symbolsPath):
# XXX: This will have to be updated after crash reporting on b2g
# is in place.
@ -160,7 +174,11 @@ class B2GRemoteAutomation(Automation):
serial, status = self.getDeviceStatus()
# reboot!
self._devicemanager.checkCmd(['reboot'])
self._devicemanager.runCmd(['shell', '/system/bin/reboot'])
# The above command can return while adb still thinks the device is
# connected, so wait a little bit for it to disconnect from adb.
time.sleep(10)
# wait for device to come back to previous status
print 'waiting for device to come back online after reboot'
@ -183,21 +201,26 @@ class B2GRemoteAutomation(Automation):
# to pass env variables into the B2G process, but this doesn't
# seem to matter.
instance = self.B2GInstance(self._devicemanager)
# reboot device so it starts up with the mochitest profile
# XXX: We could potentially use 'stop b2g' + 'start b2g' to achieve
# a similar effect; will see which is more stable while attempting
# to bring up the continuous integration.
if self._is_emulator:
self.restartB2G()
else:
if not self._is_emulator:
self.rebootDevice()
time.sleep(5)
#wait for wlan to come up
if not self.waitForNet():
raise Exception("network did not come up, please configure the network" +
" prior to running before running the automation framework")
# Infrequently, gecko comes up before networking does, so wait a little
# bit to give the network time to become available.
# XXX: need a more robust mechanism for this
time.sleep(40)
# stop b2g
self._devicemanager.runCmd(['shell', 'stop', 'b2g'])
time.sleep(5)
# relaunch b2g inside b2g instance
instance = self.B2GInstance(self._devicemanager)
time.sleep(5)
# Set up port forwarding again for Marionette, since any that
# existed previously got wiped out by the reboot.
@ -206,6 +229,8 @@ class B2GRemoteAutomation(Automation):
'tcp:%s' % self.marionette.port,
'tcp:%s' % self.marionette.port])
time.sleep(5)
# start a marionette session
session = self.marionette.start_session()
if 'b2g' not in session:
@ -228,26 +253,29 @@ class B2GRemoteAutomation(Automation):
def __init__(self, dm):
self.dm = dm
self.logcat_proc = None
self.stdout_proc = None
self.queue = Queue.Queue()
# Launch logcat in a separate thread, and dump all output lines
# Launch b2g in a separate thread, and dump all output lines
# into a queue. The lines in this queue are
# retrieved and returned by accessing the stdout property of
# this class.
cmd = [self.dm.adbPath]
if self.dm.deviceSerial:
cmd.extend(['-s', self.dm.deviceSerial])
cmd.append('logcat')
proc = threading.Thread(target=self._save_logcat_proc, args=(cmd, self.queue))
cmd.append('shell')
cmd.append('/system/bin/b2g.sh')
proc = threading.Thread(target=self._save_stdout_proc, args=(cmd, self.queue))
proc.daemon = True
proc.start()
def _save_logcat_proc(self, cmd, queue):
self.logcat_proc = LogcatProc(cmd, queue)
self.logcat_proc.run()
self.logcat_proc.waitForFinish()
self.logcat_proc = None
def _save_stdout_proc(self, cmd, queue):
self.stdout_proc = StdOutProc(cmd, queue)
self.stdout_proc.run()
if hasattr(self.stdout_proc, 'processOutput'):
self.stdout_proc.processOutput()
self.stdout_proc.waitForFinish(timeout=10)
self.stdout_proc = None
@property
def pid(self):
@ -257,7 +285,7 @@ class B2GRemoteAutomation(Automation):
@property
def stdout(self):
# Return any lines in the queue used by the
# logcat process handler.
# b2g process handler.
lines = []
while True:
try:

View File

@ -194,32 +194,42 @@ class B2GMochitest(Mochitest):
self.remoteProfile = options.remoteTestRoot + '/profile'
self._automation.setRemoteProfile(self.remoteProfile)
self.remoteLog = options.remoteLogFile
self.localLog = None
self.userJS = '/data/local/user.js'
self.remoteMozillaPath = '/data/b2g/mozilla'
self.remoteProfilesIniPath = os.path.join(self.remoteMozillaPath, 'profiles.ini')
self.originalProfilesIni = None
def cleanup(self, manifest, options):
# Restore the original profiles.ini.
if self.originalProfilesIni:
try:
if not options.emulator:
self.restoreProfilesIni()
os.remove(self.originalProfilesIni)
except:
pass
def copyRemoteFile(self, src, dest):
if self._dm.useDDCopy:
self._dm.checkCmdAs(['shell', 'dd', 'if=%s' % src,'of=%s' % dest])
else:
self._dm.checkCmdAs(['shell', 'cp', src, dest])
if not options.emulator:
def origUserJSExists(self):
return self._dm.fileExists('/data/local/user.js.orig')
def cleanup(self, manifest, options):
if self.localLog:
self._dm.getFile(self.remoteLog, self.localLog)
self._dm.removeFile(self.remoteLog)
self._dm.removeDir(self.remoteProfile)
# Restore the original user.js.
self._dm.checkCmdAs(['shell', 'rm', '-f', self.userJS])
if self._dm.useDDCopy:
self._dm.checkCmdAs(['shell', 'dd', 'if=%s.orig' % self.userJS, 'of=%s' % self.userJS])
else:
self._dm.checkCmdAs(['shell', 'cp', '%s.orig' % self.userJS, self.userJS])
if not options.emulator:
# Remove the test profile
self._dm.checkCmdAs(['shell', 'rm', '-r', self.remoteProfile])
if self.origUserJSExists():
# Restore the original user.js
self._dm.removeFile(self.userJS)
self.copyRemoteFile('%s.orig' % self.userJS, self.userJS)
self._dm.removeFile("%s.orig" % self.userJS)
if self._dm.fileExists('%s.orig' % self.remoteProfilesIniPath):
# Restore the original profiles.ini
self._dm.removeFile(self.remoteProfilesIniPath)
self.copyRemoteFile('%s.orig' % self.remoteProfilesIniPath,
self.remoteProfilesIniPath)
self._dm.removeFile("%s.orig" % self.remoteProfilesIniPath)
# We've restored the original profile, so reboot the device so that
# it gets picked up.
@ -313,14 +323,6 @@ class B2GMochitest(Mochitest):
options.profilePath = self.remoteProfile
return manifest
def restoreProfilesIni(self):
# restore profiles.ini on the device to its previous state
if not self.originalProfilesIni or not os.access(self.originalProfilesIni, os.F_OK):
raise DMError('Unable to install original profiles.ini; file not found: %s',
self.originalProfilesIni)
self._dm.pushFile(self.originalProfilesIni, self.remoteProfilesIniPath)
def updateProfilesIni(self, profilePath):
# update profiles.ini on the device to point to the test profile
self.originalProfilesIni = tempfile.mktemp()
@ -338,8 +340,11 @@ class B2GMochitest(Mochitest):
config.write(configfile)
self._dm.pushFile(newProfilesIni, self.remoteProfilesIniPath)
self._dm.pushFile(self.originalProfilesIni, '%s.orig' % self.remoteProfilesIniPath)
try:
os.remove(newProfilesIni)
os.remove(self.originalProfilesIni)
except:
pass
@ -369,21 +374,16 @@ user_pref("network.dns.localDomains","app://system.gaiamobile.org");\n
f.close()
# Copy the profile to the device.
self._dm.removeDir(self.remoteProfile)
self._dm.checkCmdAs(['shell', 'rm', '-r', self.remoteProfile])
if self._dm.pushDir(options.profilePath, self.remoteProfile) == None:
raise devicemanager.FileError("Unable to copy profile to device.")
# In B2G, user.js is always read from /data/local, not the profile
# directory. Backup the original user.js first so we can restore it.
self._dm.checkCmdAs(['shell', 'rm', '-f', '%s.orig' % self.userJS])
if self._dm.useDDCopy:
self._dm.checkCmdAs(['shell', 'dd', 'if=%s' % self.userJS, 'of=%s.orig' % self.userJS])
else:
self._dm.checkCmdAs(['shell', 'cp', self.userJS, '%s.orig' % self.userJS])
if not self._dm.fileExists('%s.orig' % self.userJS):
self.copyRemoteFile(self.userJS, '%s.orig' % self.userJS)
self._dm.pushFile(os.path.join(options.profilePath, "user.js"), self.userJS)
self.updateProfilesIni(self.remoteProfile)
options.profilePath = self.remoteProfile
options.logFile = self.localLog
return retVal
@ -419,7 +419,6 @@ def main():
kwargs.update({'host': options.deviceIP,
'port': options.devicePort})
dm = devicemanagerADB.DeviceManagerADB(**kwargs)
auto.setDeviceManager(dm)
options = parser.verifyRemoteOptions(options, auto)
if (options == None):
@ -435,12 +434,12 @@ def main():
sys.exit(1)
logParent = os.path.dirname(options.remoteLogFile)
dm.mkDir(logParent);
dm.mkDir(logParent)
auto.setRemoteLog(options.remoteLogFile)
auto.setServerInfo(options.webServer, options.httpPort, options.sslPort)
retVal = 1
try:
mochitest.cleanup(None, options)
retVal = mochitest.runTests(options)
except:
print "TEST-UNEXPECTED-FAIL | %s | Exception caught while running tests." % sys.exc_info()[1]