Home | History | Annotate | Download | only in audio_CrasSanity
      1 # Copyright 2015 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import time
      8 
      9 from autotest_lib.client.bin import test
     10 from autotest_lib.client.bin import utils
     11 from autotest_lib.client.common_lib.cros import chrome
     12 from autotest_lib.client.common_lib import error
     13 from autotest_lib.client.cros.audio import cras_utils
     14 
     15 _CRASH_PATH = '/var/spool/crash'
     16 _JS = """
     17 var c = new AudioContext();
     18 var o = c.createOscillator();
     19 o.connect(c.destination); o.start();
     20 """
     21 
     22 class audio_CrasSanity(test.test):
     23     """Verifies cras sanity using its status, active streams and crashes"""
     24 
     25     version = 1
     26     _check = {'crashes_on_boot': False,
     27               'stream_activation': False,
     28               'cras_status': False,
     29               'crashes_at_end': False
     30              }
     31 
     32     def run_once(self):
     33         # Check for existing cras crashes which might occur during UI bring up.
     34         # TODO: (rohitbm) check if we need to reboot the DUT before the test
     35         #       start to verify cras crashes during boot.
     36         existing_crash_reports = self.collect_cras_crash()
     37         if len(existing_crash_reports) == 0:
     38             self._check['crashes_on_boot'] = True
     39 
     40         # Capturing cras pid before startig the test.
     41         cras_pid_1 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     42 
     43         with chrome.Chrome(init_network_controller=True) as self._cr:
     44             # Push the 1st stream
     45             self.push_new_stream(self._cr.browser.tabs.New())
     46 
     47             # Capturing cras pid before opening a new set of audio streams.
     48             cras_pid_2 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     49 
     50             # Push the 2nd stream
     51             self.push_new_stream(self._cr.browser.tabs.New())
     52 
     53             # Let's play audio for sometime to ensure that
     54             # long playback is good.
     55             time.sleep(10)
     56 
     57             total_tests = 2
     58             active_streams = cras_utils.get_active_stream_count()
     59             logging.debug(
     60                 'Number of active streams after opening all tabs: %d.',
     61                 active_streams)
     62             if active_streams >= total_tests:
     63                 self._check['stream_activation'] = True
     64 
     65             # Capturing cras pid after opening all audio/video streams.
     66             cras_pid_3 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     67 
     68             # Close all open audio streams.
     69             while total_tests > 0:
     70                 self._cr.browser.tabs[total_tests].Close()
     71                 total_tests -= 1
     72                 time.sleep(1)
     73             active_streams = cras_utils.get_active_stream_count()
     74             logging.debug(
     75                 'Number of active streams after closing all tabs: %d.',
     76                 active_streams)
     77 
     78             # Capturing cras pid after closing all audio/stream streams.
     79             cras_pid_4 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     80 
     81             if cras_pid_1 == cras_pid_2 == cras_pid_3 == cras_pid_4:
     82                 self._check['cras_status'] = True
     83 
     84         new_crash_reports = self.collect_cras_crash()
     85         new_reports = list(set(new_crash_reports) -
     86                            set(existing_crash_reports))
     87         if len(new_reports) == 0:
     88             self._check['crashes_at_end'] = True
     89 
     90         err_msg = ''
     91         if self._check.values().count(False) > 0:
     92             if not self._check['crashes_on_boot']:
     93                 err_msg = ('1. Found cras crashes on boot: %s.\n'
     94                            % existing_crash_reports)
     95             if not self._check['stream_activation']:
     96                 err_msg += ('2. CRAS stream count is not matching with '
     97                             'number of streams.\n')
     98             if not self._check['cras_status']:
     99                 err_msg += ('CRAS PID changed during the test. CRAS might be '
    100                             'crashing while adding/removing streams.\n')
    101             if not self._check['crashes_at_end']:
    102                 err_msg += ('Found cras crashes at the end of the test : %s.' %
    103                             new_reports)
    104             raise error.TestError(err_msg)
    105 
    106 
    107     def push_new_stream(self, tab):
    108         """Starts next audio stream from self._streams list.
    109 
    110         @param tab: tab to open an audio stream.
    111         """
    112         tab.Activate()
    113         tab.Navigate("file:///")
    114         tab.ExecuteJavaScript(_JS)
    115         time.sleep(1) # Adding a delay so cras can update the active count.
    116 
    117 
    118     def collect_cras_crash(self):
    119         """Check for cras crashes.
    120 
    121         @return a list of cras crash reports found.
    122         """
    123 
    124         crash_reports = []
    125         if not os.path.isdir(_CRASH_PATH):
    126             logging.debug('No cras crash detected!')
    127         else:
    128             cras_reports = os.listdir(_CRASH_PATH)
    129             crash_reports = [report for report in cras_reports
    130                              if report.startswith('cras')]
    131         return crash_reports
    132