| # Copyright 2015 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import os |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.bin import utils |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros.audio import cras_utils |
| |
| _CRASH_PATH = '/var/spool/crash' |
| _JS = """ |
| var c = new AudioContext(); |
| var o = c.createOscillator(); |
| o.connect(c.destination); o.start(); |
| """ |
| |
| class audio_CrasSanity(test.test): |
| """Verifies cras sanity using its status, active streams and crashes""" |
| |
| version = 1 |
| _check = {'crashes_on_boot': False, |
| 'stream_activation': False, |
| 'cras_status': False, |
| 'crashes_at_end': False |
| } |
| |
| def run_once(self): |
| # Check for existing cras crashes which might occur during UI bring up. |
| # TODO: (rohitbm) check if we need to reboot the DUT before the test |
| # start to verify cras crashes during boot. |
| existing_crash_reports = self.collect_cras_crash() |
| if len(existing_crash_reports) == 0: |
| self._check['crashes_on_boot'] = True |
| |
| # Capturing cras pid before startig the test. |
| cras_pid_1 = utils.get_oldest_pid_by_name('/usr/bin/cras') |
| |
| with chrome.Chrome(init_network_controller=True) as self._cr: |
| # Push the 1st stream |
| self.push_new_stream(self._cr.browser.tabs.New()) |
| |
| # Capturing cras pid before opening a new set of audio streams. |
| cras_pid_2 = utils.get_oldest_pid_by_name('/usr/bin/cras') |
| |
| # Push the 2nd stream |
| self.push_new_stream(self._cr.browser.tabs.New()) |
| |
| # Let's play audio for sometime to ensure that |
| # long playback is good. |
| time.sleep(10) |
| |
| total_tests = 2 |
| active_streams = cras_utils.get_active_stream_count() |
| logging.debug( |
| 'Number of active streams after opening all tabs: %d.', |
| active_streams) |
| if active_streams >= total_tests: |
| self._check['stream_activation'] = True |
| |
| # Capturing cras pid after opening all audio/video streams. |
| cras_pid_3 = utils.get_oldest_pid_by_name('/usr/bin/cras') |
| |
| # Close all open audio streams. |
| while total_tests > 0: |
| self._cr.browser.tabs[total_tests].Close() |
| total_tests -= 1 |
| time.sleep(1) |
| active_streams = cras_utils.get_active_stream_count() |
| logging.debug( |
| 'Number of active streams after closing all tabs: %d.', |
| active_streams) |
| |
| # Capturing cras pid after closing all audio/stream streams. |
| cras_pid_4 = utils.get_oldest_pid_by_name('/usr/bin/cras') |
| |
| if cras_pid_1 == cras_pid_2 == cras_pid_3 == cras_pid_4: |
| self._check['cras_status'] = True |
| |
| new_crash_reports = self.collect_cras_crash() |
| new_reports = list(set(new_crash_reports) - |
| set(existing_crash_reports)) |
| if len(new_reports) == 0: |
| self._check['crashes_at_end'] = True |
| |
| err_msg = '' |
| if self._check.values().count(False) > 0: |
| if not self._check['crashes_on_boot']: |
| err_msg = ('1. Found cras crashes on boot: %s.\n' |
| % existing_crash_reports) |
| if not self._check['stream_activation']: |
| err_msg += ('2. CRAS stream count is not matching with ' |
| 'number of streams.\n') |
| if not self._check['cras_status']: |
| err_msg += ('CRAS PID changed during the test. CRAS might be ' |
| 'crashing while adding/removing streams.\n') |
| if not self._check['crashes_at_end']: |
| err_msg += ('Found cras crashes at the end of the test : %s.' % |
| new_reports) |
| raise error.TestError(err_msg) |
| |
| |
| def push_new_stream(self, tab): |
| """Starts next audio stream from self._streams list. |
| |
| @param tab: tab to open an audio stream. |
| """ |
| tab.Activate() |
| tab.Navigate("file:///") |
| tab.ExecuteJavaScript(_JS) |
| time.sleep(1) # Adding a delay so cras can update the active count. |
| |
| |
| def collect_cras_crash(self): |
| """Check for cras crashes. |
| |
| @return a list of cras crash reports found. |
| """ |
| |
| crash_reports = [] |
| if not os.path.isdir(_CRASH_PATH): |
| logging.debug('No cras crash detected!') |
| else: |
| cras_reports = os.listdir(_CRASH_PATH) |
| crash_reports = [report for report in cras_reports |
| if report.startswith('cras')] |
| return crash_reports |