• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
5import logging
6import os
7import time
8
9from autotest_lib.client.bin import test
10from autotest_lib.client.bin import utils
11from autotest_lib.client.common_lib.cros import chrome
12from autotest_lib.client.common_lib import error
13from autotest_lib.client.cros.audio import cras_utils
14
15_CRASH_PATH = '/var/spool/crash'
16_JS = """
17var c = new AudioContext();
18var o = c.createOscillator();
19o.connect(c.destination); o.start();
20"""
21
22class 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