Bug 843296 - check for crashes in b2g emulator unittests during failures in marionette start up, r=jgriffin

This commit is contained in:
Andrew Halberstadt 2013-03-26 09:50:00 -04:00
parent 29e85efb07
commit f7f283237c
7 changed files with 82 additions and 5 deletions

View File

@ -10,6 +10,7 @@ import re
import shutil import shutil
import tempfile import tempfile
import time import time
import traceback
from automation import Automation from automation import Automation
from devicemanager import NetworkTools from devicemanager import NetworkTools
@ -106,11 +107,14 @@ class B2GRemoteAutomation(Automation):
def checkForCrashes(self, directory, symbolsPath): def checkForCrashes(self, directory, symbolsPath):
crashed = False crashed = False
remote_dump_dir = self._remoteProfile + '/minidumps' remote_dump_dir = self._remoteProfile + '/minidumps'
print "checking for crashes in '%s'" % remote_dump_dir
if self._devicemanager.dirExists(remote_dump_dir): if self._devicemanager.dirExists(remote_dump_dir):
local_dump_dir = tempfile.mkdtemp() local_dump_dir = tempfile.mkdtemp()
self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir) self._devicemanager.getDirectory(remote_dump_dir, local_dump_dir)
try: try:
crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen) crashed = mozcrash.check_for_crashes(local_dump_dir, symbolsPath, test_name=self.lastTestSeen)
except:
traceback.print_exc()
finally: finally:
shutil.rmtree(local_dump_dir) shutil.rmtree(local_dump_dir)
self._devicemanager.removeDir(remote_dump_dir) self._devicemanager.removeDir(remote_dump_dir)

View File

@ -480,6 +480,8 @@ def main(args=sys.argv[1:]):
kwargs['logcat_dir'] = options.logcat_dir kwargs['logcat_dir'] = options.logcat_dir
if options.busybox: if options.busybox:
kwargs['busybox'] = options.busybox kwargs['busybox'] = options.busybox
if options.symbolsPath:
kwargs['symbols_path'] = options.symbolsPath
if options.emulator_res: if options.emulator_res:
kwargs['emulator_res'] = options.emulator_res kwargs['emulator_res'] = options.emulator_res
if options.b2gPath: if options.b2gPath:

View File

@ -2,10 +2,18 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # 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/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
from ConfigParser import ConfigParser
import os import os
import platform import platform
import posixpath
import shutil
import subprocess import subprocess
import sys import sys
import tempfile
import traceback
from mozdevice import DeviceManagerADB
import mozcrash
class B2GInstance(object): class B2GInstance(object):
@classmethod @classmethod
@ -68,7 +76,7 @@ class B2GInstance(object):
return option return option
raise Exception('%s not found!' % binary) raise Exception('%s not found!' % binary)
def __init__(self, homedir=None): def __init__(self, homedir=None, devicemanager=None):
if not homedir: if not homedir:
homedir = self.find_b2g_dir() homedir = self.find_b2g_dir()
else: else:
@ -81,6 +89,13 @@ class B2GInstance(object):
self.adb_path = self.check_adb(self.homedir) self.adb_path = self.check_adb(self.homedir)
self.fastboot_path = self.check_fastboot(self.homedir) self.fastboot_path = self.check_fastboot(self.homedir)
self.update_tools = os.path.join(self.homedir, 'tools', 'update-tools') self.update_tools = os.path.join(self.homedir, 'tools', 'update-tools')
self._dm = devicemanager
@property
def dm(self):
if not self._dm:
self._dm = DeviceManagerADB(adbPath=self.adb_path)
return self._dm
def check_file(self, filePath): def check_file(self, filePath):
if not os.access(filePath, os.F_OK): if not os.access(filePath, os.F_OK):
@ -88,6 +103,43 @@ class B2GInstance(object):
'directory as the homedir parameter, or set ' 'directory as the homedir parameter, or set '
'B2G_HOME correctly?') % filePath) 'B2G_HOME correctly?') % filePath)
def check_remote_profiles(self, remote_profiles_ini='/data/b2g/mozilla/profiles.ini'):
if not self.dm.fileExists(remote_profiles_ini):
raise Exception("Remote file '%s' not found" % remote_profiles_ini)
local_profiles_ini = tempfile.NamedTemporaryFile()
self.dm.getFile(remote_profiles_ini, local_profiles_ini.name)
cfg = ConfigParser()
cfg.readfp(local_profiles_ini)
remote_profiles = []
for section in cfg.sections():
if cfg.has_option(section, 'Path'):
is_relative = 0
if cfg.has_option(section, 'IsRelative'):
is_relative = cfg.getint(section, 'IsRelative')
remote_profiles.append(posixpath.join(remote_profiles_ini, cfg.get(section, 'Path'))
if is_relative else cfg.get(section, 'Path'))
return remote_profiles
def check_for_crashes(self, symbols_path):
remote_dump_dirs = [posixpath.join(p, 'minidumps') for p in self.check_remote_profiles()]
crashed = False
for remote_dump_dir in remote_dump_dirs:
print "checking for crashes in '%s'" % remote_dump_dir
local_dump_dir = tempfile.mkdtemp()
self.dm.getDirectory(remote_dump_dir, local_dump_dir)
try:
if mozcrash.check_for_crashes(local_dump_dir, symbols_path):
crashed = True
except:
traceback.print_exc()
finally:
shutil.rmtree(local_dump_dir)
self.dm.removeDir(remote_dump_dir)
return crashed
def import_update_tools(self): def import_update_tools(self):
"""Import the update_tools package from B2G""" """Import the update_tools package from B2G"""
sys.path.append(self.update_tools) sys.path.append(self.update_tools)

View File

@ -162,6 +162,9 @@ class Emulator(object):
return True return True
return False return False
def check_for_minidumps(self, symbols_path):
return self.b2g.check_for_crashes(symbols_path)
def create_sdcard(self, sdcard): def create_sdcard(self, sdcard):
self._tmp_sdcard = tempfile.mktemp(prefix='sdcard') self._tmp_sdcard = tempfile.mktemp(prefix='sdcard')
sdargs = [self.mksdcard, "-l", "mySdCard", sdcard, self._tmp_sdcard] sdargs = [self.mksdcard, "-l", "mySdCard", sdcard, self._tmp_sdcard]

View File

@ -168,7 +168,7 @@ class Marionette(object):
emulator=None, sdcard=None, emulatorBinary=None, emulator=None, sdcard=None, emulatorBinary=None,
emulatorImg=None, emulator_res=None, gecko_path=None, emulatorImg=None, emulator_res=None, gecko_path=None,
connectToRunningEmulator=False, homedir=None, baseurl=None, connectToRunningEmulator=False, homedir=None, baseurl=None,
noWindow=False, logcat_dir=None, busybox=None): noWindow=False, logcat_dir=None, busybox=None, symbols_path=None):
self.host = host self.host = host
self.port = self.local_port = port self.port = self.local_port = port
self.bin = bin self.bin = bin
@ -183,6 +183,7 @@ class Marionette(object):
self.noWindow = noWindow self.noWindow = noWindow
self.logcat_dir = logcat_dir self.logcat_dir = logcat_dir
self._test_name = None self._test_name = None
self.symbols_path = symbols_path
if bin: if bin:
port = int(self.port) port = int(self.port)
@ -366,10 +367,15 @@ class Marionette(object):
def check_for_crash(self): def check_for_crash(self):
returncode = None returncode = None
name = None name = None
crashed = False
if self.emulator: if self.emulator:
if self.emulator.check_for_crash(): if self.emulator.check_for_crash():
returncode = self.emulator.proc.returncode returncode = self.emulator.proc.returncode
name = 'emulator' name = 'emulator'
crashed = True
if self.symbols_path and self.emulator.check_for_minidumps(self.symbols_path):
crashed = True
elif self.instance: elif self.instance:
# In the future, a check for crashed Firefox processes # In the future, a check for crashed Firefox processes
# should be here. # should be here.
@ -377,7 +383,7 @@ class Marionette(object):
if returncode is not None: if returncode is not None:
print ('PROCESS-CRASH | %s | abnormal termination with exit code %d' % print ('PROCESS-CRASH | %s | abnormal termination with exit code %d' %
(name, returncode)) (name, returncode))
return returncode is not None return crashed
def absolute_url(self, relative_url): def absolute_url(self, relative_url):
return "%s%s" % (self.baseurl, relative_url) return "%s%s" % (self.baseurl, relative_url)
@ -386,8 +392,14 @@ class Marionette(object):
return self._send_message('getStatus', 'value') return self._send_message('getStatus', 'value')
def start_session(self, desired_capabilities=None): def start_session(self, desired_capabilities=None):
# We are ignoring desired_capabilities, at least for now. try:
self.session = self._send_message('newSession', 'value') # We are ignoring desired_capabilities, at least for now.
self.session = self._send_message('newSession', 'value')
except:
traceback.print_exc()
self.check_for_crash()
sys.exit()
self.b2g = 'b2g' in self.session self.b2g = 'b2g' in self.session
return self.session return self.session

View File

@ -566,6 +566,8 @@ def run_remote_mochitests(automation, parser, options):
kwargs['logcat_dir'] = options.logcat_dir kwargs['logcat_dir'] = options.logcat_dir
if options.busybox: if options.busybox:
kwargs['busybox'] = options.busybox kwargs['busybox'] = options.busybox
if options.symbolsPath:
kwargs['symbols_path'] = options.symbolsPath
# needless to say sdcard is only valid if using an emulator # needless to say sdcard is only valid if using an emulator
if options.sdcard: if options.sdcard:
kwargs['sdcard'] = options.sdcard kwargs['sdcard'] = options.sdcard

View File

@ -167,6 +167,8 @@ def main():
kwargs['logcat_dir'] = options.logcat_dir kwargs['logcat_dir'] = options.logcat_dir
if options.busybox: if options.busybox:
kwargs['busybox'] = options.busybox kwargs['busybox'] = options.busybox
if options.symbolsPath:
kwargs['symbols_path'] = options.symbolsPath
if options.b2g_path: if options.b2g_path:
kwargs['homedir'] = options.emu_path or options.b2g_path kwargs['homedir'] = options.emu_path or options.b2g_path
if options.address: if options.address: