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 _DOWNLOAD_BASE = ('http://commondatastorage.googleapis.com/'
     17                   'chromiumos-test-assets-public/')
     18 
     19 
     20 class audio_CrasSanity(test.test):
     21     """Verifies cras sanity using its status, active streams and crashes"""
     22 
     23     version = 1
     24 
     25     _audio = ('audio.mp3', 'audio.wav', 'audio.m4a')
     26     _video = ('traffic-1920x1080-8005020218f6b86bfa978e550d04956e.mp4',
     27               'traffic-1920x1080-ad53f821ff3cf8ffa7e991c9d2e0b854.vp8.webm',
     28               'traffic-1920x1080-83a1e5f8b7944577425f039034e64c76.vp9.webm')
     29 
     30     _check = {'crashes_on_boot': False,
     31               'stream_activation': False,
     32               'cras_status': False,
     33               'crashes_at_end': False
     34              }
     35 
     36     def run_once(self):
     37         boards_to_skip = ['x86-mario']
     38         dut_board = utils.get_current_board()
     39         if dut_board in boards_to_skip:
     40             logging.info("Skipping test run on this board.")
     41             return
     42         # Check for existing cras crashes which might occur during UI bring up.
     43         # TODO: (rohitbm) check if we need to reboot the DUT before the test
     44         #       start to verify cras crashes during boot.
     45         existing_crash_reports = self.collect_cras_crash()
     46         if len(existing_crash_reports) == 0:
     47             self._check['crashes_on_boot'] = True
     48 
     49         # Capturing cras pid before startig the test.
     50         cras_pid_1 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     51 
     52         with chrome.Chrome(init_network_controller=True) as self._cr:
     53             try:
     54                 # This will be used on Chrome PFQ since it's using a more recent
     55                 # version of Chrome. crbug.com/537655.
     56                 self._cr.browser.platform.SetHTTPServerDirectories(self.bindir)
     57             except:
     58                 # This will be used on ChromeOS CQ since Chrome hasn't uprev'ed
     59                 # yet. crbug.com/538140.
     60                 self._cr.browser.SetHTTPServerDirectories(self.bindir)
     61             for test_file in self._audio:
     62                 url = _DOWNLOAD_BASE + 'audio_test/' + test_file
     63                 self.push_new_stream(self._cr.browser.tabs.New(), url)
     64 
     65             # Capturing cras pid before opening a new set of audio streams.
     66             cras_pid_2 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     67             for test_file in self._video:
     68                 url = _DOWNLOAD_BASE + 'traffic/' + test_file
     69                 self.push_new_stream(self._cr.browser.tabs.New(), url)
     70 
     71             # Let's play audio for sometime to ensure that
     72             # long playback is good.
     73             time.sleep(10)
     74 
     75             total_tests = len(self._audio) + len(self._video)
     76             active_streams = cras_utils.get_active_stream_count()
     77             logging.debug(
     78                 'Number of active streams after opening all tabs: %d.',
     79                 active_streams)
     80             if active_streams >= total_tests:
     81                 self._check['stream_activation'] = True
     82 
     83             # Capturing cras pid after opening all audio/video streams.
     84             cras_pid_3 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     85 
     86             # Close all open audio streams.
     87             while total_tests > 0:
     88                 self._cr.browser.tabs[total_tests].Close()
     89                 total_tests -= 1
     90                 time.sleep(1)
     91             active_streams = cras_utils.get_active_stream_count()
     92             logging.debug(
     93                 'Number of active streams after closing all tabs: %d.',
     94                 active_streams)
     95 
     96             # Capturing cras pid after closing all audio/stream streams.
     97             cras_pid_4 = utils.get_oldest_pid_by_name('/usr/bin/cras')
     98 
     99             if cras_pid_1 == cras_pid_2 == cras_pid_3 == cras_pid_4:
    100                 self._check['cras_status'] = True
    101 
    102         new_crash_reports = self.collect_cras_crash()
    103         new_reports = list(set(new_crash_reports) -
    104                            set(existing_crash_reports))
    105         if len(new_reports) == 0:
    106             self._check['crashes_at_end'] = True
    107 
    108         err_msg = ''
    109         if self._check.values().count(False) > 0:
    110             if not self._check['crashes_on_boot']:
    111                 err_msg = ('1. Found cras crashes on boot: %s.\n'
    112                            % existing_crash_reports)
    113             if not self._check['stream_activation']:
    114                 err_msg += ('2. CRAS stream count is not matching with '
    115                             'number of streams.\n')
    116             if not self._check['cras_status']:
    117                 err_msg += ('CRAS PID changed during the test. CRAS might be '
    118                             'crashing while adding/removing streams.\n')
    119             if not self._check['crashes_at_end']:
    120                 err_msg += ('Found cras crashes at the end of the test : %s.' %
    121                             new_reports)
    122             raise error.TestError(err_msg)
    123 
    124 
    125     def push_new_stream(self, tab, url):
    126         """Starts next audio stream from self._streams list.
    127 
    128         @param tab: tab to open an audio stream.
    129         @param url: audio/video test url.
    130         """
    131         tab.Activate()
    132         tab.Navigate(url)
    133         tab.ExecuteJavaScript(
    134                 "document.getElementsByTagName('video')[0].loop=true")
    135         tab.ExecuteJavaScript(
    136                 "document.getElementsByTagName('video')[0].volume=0.1")
    137         time.sleep(1) # Adding a delay so cras can update the active count.
    138 
    139 
    140     def collect_cras_crash(self):
    141         """Check for cras crashes.
    142 
    143         @return a list of cras crash reports found.
    144         """
    145 
    146         crash_reports = []
    147         if not os.path.isdir(_CRASH_PATH):
    148             logging.debug('No cras crash detected!')
    149         else:
    150             cras_reports = os.listdir(_CRASH_PATH)
    151             crash_reports = [report for report in cras_reports
    152                              if report.startswith('cras')]
    153         return crash_reports
    154