Skip to content
Browse files

Bug 851288 - Use quitter.xpi for terminating fennec in autophone s1s2…

… tests, r=mcote.
  • Loading branch information...
1 parent cbcf1ca commit cfce5c69f7240287967891aa65b3f142fee6b773 @bclary bclary committed Mar 19, 2013
Showing with 76 additions and 20 deletions.
  1. +4 −0 INSTALL.md
  2. +4 −0 configs/s1s2_settings.ini.example
  3. +14 −0 phonetest.py
  4. +54 −20 tests/s1s2test.py
  5. BIN xpi/quitter.xpi
View
4 INSTALL.md
@@ -41,6 +41,7 @@ The s1s2 test is configured in the file configs/s1s2_settings.ini:
file3 = configs/Twitter_files
file1 = configs/startup6.html
file2 = configs/Twitter2.html
+ file4 = configs/initialize_profile.html
[urls]
# These must resolve, so ensure this matches what is in the code for
@@ -53,6 +54,9 @@ The s1s2 test is configured in the file configs/s1s2_settings.ini:
[settings]
iterations = 20
resulturl = http://192.168.1.133:8100/api/s1s2_add/
+ # initialize_url is loaded prior to the other urls in order to
+ # initialize the profile.
+ initialize_url = file://mnt/sdcard/s1test/initialize_profile.html
[htmlfiles] contains the paths of files to transfer to the phone. [urls]
lists local and remote URLs (FIXME: we could make this less redundant).
View
4 configs/s1s2_settings.ini.example
@@ -2,6 +2,7 @@
file3 = configs/Twitter_files
file1 = configs/startup6.html
file2 = configs/Twitter2.html
+file4 = configs/initialize_profile.html
[urls]
# These must resolve, so ensure this matches what is in the code for
@@ -14,3 +15,6 @@ remote-blank = http://10.250.50.162/startup6.html
[settings]
iterations = 20
resulturl = http://10.250.2.223:8100/api/s1s2_add/
+# initialize_url is loaded prior to the other urls in order to
+# initialize the profile.
+initialize_url = file://mnt/sdcard/s1test/initialize_profile.html
View
14 phonetest.py
@@ -3,8 +3,10 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
import datetime
+import glob
import json
import logging
+import os
import StringIO
from mozdevice import DeviceManagerSUT
@@ -133,3 +135,15 @@ def run_fennec_with_profile(self, intent, url):
def remove_sessionstore_files(self):
self.dm.removeFile(self.profile_path + '/sessionstore.js')
self.dm.removeFile(self.profile_path + '/sessionstore.bak')
+
+ def check_for_crashes(self):
+ """
+ Perform a quick check for crashes by checking
+ self.profile_path/minidumps for dump files.
+
+ TODO: Should use mozbase/mozcrash with symbols and minidump_stackwalk
+ to process and report crashes.
+ """
+ if glob.glob(os.path.join(self.profile_path, 'minidumps', '*.dmp')):
+ return True
+ return False
View
74 tests/s1s2test.py
@@ -24,6 +24,15 @@ def runjob(self, job, worker_subprocess):
intent = job['androidprocname'] + '/.App'
+ # Initialize profile
+ self.logger.debug('initializing profile...')
+ self.run_fennec_with_profile(intent, self._initialize_url)
+ if not self.wait_for_fennec(job):
+ self.logger.info('%s: Failed to initialize profile for build %s' %
+ (self.phone_cfg['phoneid'], job['buildid']))
+ self.set_status(msg='Failed to initialize profile for build %s' % job['buildid'])
+ return
+
for testnum,(testname,url) in enumerate(self._urls.iteritems(), 1):
self.logger.info('%s: Running test %s (%d/%d) for %s iterations' %
(self.phone_cfg['phoneid'], testname, testnum,
@@ -57,19 +66,9 @@ def runjob(self, job, worker_subprocess):
# parse in logcat.
throbberstart, throbberstop = self.analyze_logcat(job)
- self.logger.debug('killing fennec')
- # Get rid of the browser and session store files
- max_killattempts = 3
- for kill_attempt in range(max_killattempts):
- try:
- self.dm.killProcess(job['androidprocname'])
- break
- except DMError:
- self.logger.info('Attempt %d to kill fennec failed' % kill_attempt)
- if kill_attempt == max_killattempts - 1:
- raise
- sleep(20)
+ self.wait_for_fennec(job)
+ # Get rid of the browser and session store files
self.logger.debug('removing sessionstore files')
self.remove_sessionstore_files()
@@ -90,6 +89,32 @@ def runjob(self, job, worker_subprocess):
job=job,
testname=testname)
+ def wait_for_fennec(self, job, max_wait_time=60, wait_time=5, kill_wait_time=20):
+ # Wait for up to a max_wait_time seconds for fennec to close
+ # itself in response to the quitter request. Check that fennec
+ # is still running every wait_time seconds. If fennec doesn't
+ # close on its own, attempt up to 3 times to kill fennec, waiting
+ # kill_wait_time seconds between attempts.
+ # Return True if fennec exits on its own, False if it needs to be killed.
+ # Re-raise the last exception if fennec can not be killed.
+ max_wait_attempts = max_wait_time / wait_time
+ for wait_attempt in range(max_wait_attempts):
+ if not self.dm.processExist(job['androidprocname']):
+ return True
+ sleep(wait_time)
+ self.logger.debug('killing fennec')
+ max_killattempts = 3
+ for kill_attempt in range(max_killattempts):
+ try:
+ self.dm.killProcess(job['androidprocname'])
+ break
+ except DMError:
+ self.logger.info('Attempt %d to kill fennec failed' % kill_attempt)
+ if kill_attempt == max_killattempts - 1:
+ raise
+ sleep(kill_wait_time)
+ return False
+
def prepare_phone(self, job):
telemetry_prompt = 999
if job['blddate'] < '2013-01-03':
@@ -102,7 +127,8 @@ def prepare_phone(self, job):
'browser.EULA.override': True,
'toolkit.telemetry.prompted': telemetry_prompt,
'toolkit.telemetry.notifiedOptOut': telemetry_prompt }
- profile = FirefoxProfile(preferences=prefs)
+ profile = FirefoxProfile(preferences=prefs, addons='%s/xpi/quitter.xpi' %
+ os.getcwd())
self.install_profile(profile)
self.dm.mkDir('/mnt/sdcard/s1test')
@@ -135,6 +161,7 @@ def prepare_phone(self, job):
self._iterations = cfg.getint('settings', 'iterations')
self._resulturl = cfg.get('settings', 'resulturl')
+ self._initialize_url = cfg.get('settings', 'initialize_url')
def analyze_logcat(self, job):
self.logger.debug('analyzing logcat')
@@ -147,12 +174,14 @@ def analyze_logcat(self, job):
wait_time = 3 # time to wait between attempts
max_attempts = max_time / wait_time
- fennec_crashed = False
- while attempt < max_attempts and (throbstart == 0 or throbstop == 0):
+ # Always do at least one analysis of the logcat output
+ # after fennec stops running to make sure we have not missed
+ # throbberstop.
+ fennec_still_running = True
+ while (fennec_still_running and
+ attempt < max_attempts and (throbstart == 0 or throbstop == 0)):
if not self.dm.processExist(job['androidprocname']):
- self.logger.info('analyze_logcat: fennec is no longer running...')
- fennec_crashed = True
- break
+ fennec_still_running = False
buf = [x.strip() for x in self.dm.getLogcat()]
for line in buf:
# we want the first throbberstart and throbberstop.
@@ -162,10 +191,15 @@ def analyze_logcat(self, job):
throbstop = line.split(' ')[-4]
if throbstart and throbstop:
break
- if throbstart == 0 or throbstop == 0:
+ if fennec_still_running and (throbstart == 0 or throbstop == 0):
sleep(wait_time)
attempt += 1
- if not fennec_crashed and throbstart and throbstop == 0:
+ if self.check_for_crashes():
+ self.logger.info('fennec crashed')
+ fennec_crashed = True
+ else:
+ fennec_crashed = False
+ if throbstart and throbstop == 0 and not fennec_crashed:
throbstop = int(throbstart) + max_time * 1000
return (int(throbstart), int(throbstop))
View
BIN xpi/quitter.xpi
Binary file not shown.

0 comments on commit cfce5c6

Please sign in to comment.
Something went wrong with that request. Please try again.