• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2014 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 random
8import time
9
10from autotest_lib.client.bin import test
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_STRESS_ITERATIONS = 100 # Total number of iterations.
16_MAX_OPENED_TAB = 20     # Max number of tabs open and playing audio.
17_RETAIN_TAB = 5          # In case we hit the _MAX_OPENED_TAB limit,
18                         # close all except last 5 tabs.
19_MAX_TABS_TO_OPEN = 10   # Max number of tabs can be opened in one iteration.
20_CRASH_PATH = '/var/spool/crash'
21
22
23class audio_ActiveStreamStress(test.test):
24    """Verifies the active audio streams."""
25
26    version = 1
27
28    _active_stream_count = 0
29    _existing_cras_reports = []
30    _cr = None
31    # TODO(rohitbm): add more(including video) file types and download them from gs://.
32    _streams = ('audio.mp3', 'audio.wav', 'audio.m4a')
33    _stream_index = 0
34    _tab_count = 0
35
36    def run_once(self):
37
38        # Collect existing cras crash reports.
39        self._existing_cras_reports = self.collect_cras_crash()
40
41        with chrome.Chrome(init_network_controller=True) as self._cr:
42            self._cr.browser.platform.SetHTTPServerDirectories(self.bindir)
43            self.push_new_stream(self._cr.browser.tabs[0])
44            # TODO(rohitbm): decide whether to perform verification on each
45            # open/close or at end of the iteration.
46            self.verify_active_streams()
47            push_count = 0
48            pop_count = 0
49
50            # Stress test logic:
51            # Test runs for n number of iterations. For one iteration,
52            # a = random(10) tabs(streams) are created and
53            # b = random(a) tabs are closed. If the next iteration finds that,
54            # total number of opened tabs are more than _MAX_OPENED_TAB,
55            # test will close (total opened tabs - 5) tabs.
56            # This will balance number of opened tabs and will allow to close
57            # tabs in a control manner.
58
59            for count in xrange(1, _STRESS_ITERATIONS):
60                if self._tab_count > _MAX_OPENED_TAB:
61                     for i in xrange(1, (self._tab_count - _RETAIN_TAB)):
62                         pop_count += 1
63                         self.pop_stream()
64                         logging.info('Total streams closed: %d', pop_count)
65                random_tab = random.randint(1, 10)
66                for i in xrange(1, random_tab):
67                    push_count += 1
68                    self.push_new_stream(self._cr.browser.tabs.New())
69                    logging.info('Total new streams created: %d', push_count)
70                time.sleep(5) # Delay for active streams to play.
71                for i in xrange(1, random.randint(1, random_tab)):
72                    pop_count += 1
73                    self.pop_stream()
74                    logging.info('Total streams closed: %d', pop_count)
75
76
77    def get_stream_index(self):
78        if self._stream_index == len(self._streams):
79            # Reset the stream index if the index reached to the end.
80            self._stream_index = 0
81        return self._stream_index
82
83
84    def push_new_stream(self, tab):
85        """Starts next audio stream from self._streams list.
86
87        @param tab: tab to open an audio stream.
88        """
89        self._tab_count += 1
90        tab.Navigate(self._cr.browser.platform.http_server.UrlOf(
91                    os.path.join(self.bindir,
92                                 self._streams[self.get_stream_index()])))
93        tab.ExecuteJavaScript(
94                "document.getElementsByTagName('video')[0].loop=true")
95        # TODO(rohitbm): add playback verification.
96        self._stream_index += 1
97        self._active_stream_count += 1
98        time.sleep(1) # Adding a delay so cras can update the active count.
99        self.verify_active_streams()
100
101
102    def pop_stream(self):
103        """Turns off the first available stream by closing the first tab."""
104        if len(self._cr.browser.tabs) > 0:
105            self._cr.browser.tabs[0].Close()
106            self._tab_count -= 1
107            self._active_stream_count -= 1
108        time.sleep(1) # Adding delay so cras can update the active count.
109        self.verify_active_streams()
110
111
112    def verify_active_streams(self):
113        """Verifies test active audio streams with cras active streams."""
114        cras_stream_count = cras_utils.get_active_stream_count()
115        if self._active_stream_count != cras_stream_count:
116            cras_crash_reports = self.collect_cras_crash()
117            new_reports = list(set(cras_crash_reports) -
118                               set(self._existing_cras_reports))
119            error_msg = ('Active stream count: %d is not matching with '
120                         'cras active stream count: %d. '
121                         'Number of cras crashes %d : %s' %
122                         (self._active_stream_count, cras_stream_count,
123                         len(new_reports), new_reports))
124            raise error.TestError(error_msg)
125
126
127    def collect_cras_crash(self):
128        """Check for cras crashes.
129
130        @return a list of cras crash reports found.
131        """
132
133        crash_reports = []
134        if not os.path.isdir(_CRASH_PATH):
135            logging.debug('No cras crash detected!')
136        else:
137            cras_reports = os.listdir(_CRASH_PATH)
138            crash_reports = [report for report in cras_reports
139                             if report.startswith('cras')]
140        return crash_reports
141