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