• 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_DOWNLOAD_BASE = ('http://commondatastorage.googleapis.com/'
17                  'chromiumos-test-assets-public/')
18
19
20class 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