| # Copyright 2014 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| import logging |
| import os |
| import random |
| import time |
| |
| from autotest_lib.client.bin import test |
| from autotest_lib.client.common_lib.cros import chrome |
| from autotest_lib.client.common_lib import error |
| from autotest_lib.client.cros.audio import cras_utils |
| |
| _STRESS_ITERATIONS = 100 # Total number of iterations. |
| _MAX_OPENED_TAB = 20 # Max number of tabs open and playing audio. |
| _RETAIN_TAB = 5 # In case we hit the _MAX_OPENED_TAB limit, |
| # close all except last 5 tabs. |
| _MAX_TABS_TO_OPEN = 10 # Max number of tabs can be opened in one iteration. |
| _CRASH_PATH = '/var/spool/crash' |
| |
| |
| class audio_ActiveStreamStress(test.test): |
| """Verifies the active audio streams.""" |
| |
| version = 1 |
| |
| _active_stream_count = 0 |
| _existing_cras_reports = [] |
| _cr = None |
| # TODO(rohitbm): add more(including video) file types and download them from gs://. |
| _streams = ('audio.mp3', 'audio.wav', 'audio.m4a') |
| _stream_index = 0 |
| _tab_count = 0 |
| |
| def run_once(self): |
| |
| # Collect existing cras crash reports. |
| self._existing_cras_reports = self.collect_cras_crash() |
| |
| with chrome.Chrome(init_network_controller=True) as self._cr: |
| self._cr.browser.platform.SetHTTPServerDirectories(self.bindir) |
| self.push_new_stream(self._cr.browser.tabs[0]) |
| # TODO(rohitbm): decide whether to perform verification on each |
| # open/close or at end of the iteration. |
| self.verify_active_streams() |
| push_count = 0 |
| pop_count = 0 |
| |
| # Stress test logic: |
| # Test runs for n number of iterations. For one iteration, |
| # a = random(10) tabs(streams) are created and |
| # b = random(a) tabs are closed. If the next iteration finds that, |
| # total number of opened tabs are more than _MAX_OPENED_TAB, |
| # test will close (total opened tabs - 5) tabs. |
| # This will balance number of opened tabs and will allow to close |
| # tabs in a control manner. |
| |
| for count in xrange(1, _STRESS_ITERATIONS): |
| if self._tab_count > _MAX_OPENED_TAB: |
| for i in xrange(1, (self._tab_count - _RETAIN_TAB)): |
| pop_count += 1 |
| self.pop_stream() |
| logging.info('Total streams closed: %d', pop_count) |
| random_tab = random.randint(1, 10) |
| for i in xrange(1, random_tab): |
| push_count += 1 |
| self.push_new_stream(self._cr.browser.tabs.New()) |
| logging.info('Total new streams created: %d', push_count) |
| time.sleep(5) # Delay for active streams to play. |
| for i in xrange(1, random.randint(1, random_tab)): |
| pop_count += 1 |
| self.pop_stream() |
| logging.info('Total streams closed: %d', pop_count) |
| |
| |
| def get_stream_index(self): |
| if self._stream_index == len(self._streams): |
| # Reset the stream index if the index reached to the end. |
| self._stream_index = 0 |
| return self._stream_index |
| |
| |
| def push_new_stream(self, tab): |
| """Starts next audio stream from self._streams list. |
| |
| @param tab: tab to open an audio stream. |
| """ |
| self._tab_count += 1 |
| tab.Navigate(self._cr.browser.platform.http_server.UrlOf( |
| os.path.join(self.bindir, |
| self._streams[self.get_stream_index()]))) |
| tab.ExecuteJavaScript( |
| "document.getElementsByTagName('video')[0].loop=true") |
| # TODO(rohitbm): add playback verification. |
| self._stream_index += 1 |
| self._active_stream_count += 1 |
| time.sleep(1) # Adding a delay so cras can update the active count. |
| self.verify_active_streams() |
| |
| |
| def pop_stream(self): |
| """Turns off the first available stream by closing the first tab.""" |
| if len(self._cr.browser.tabs) > 0: |
| self._cr.browser.tabs[0].Close() |
| self._tab_count -= 1 |
| self._active_stream_count -= 1 |
| time.sleep(1) # Adding delay so cras can update the active count. |
| self.verify_active_streams() |
| |
| |
| def verify_active_streams(self): |
| """Verifies test active audio streams with cras active streams.""" |
| cras_stream_count = cras_utils.get_active_stream_count() |
| if self._active_stream_count != cras_stream_count: |
| cras_crash_reports = self.collect_cras_crash() |
| new_reports = list(set(cras_crash_reports) - |
| set(self._existing_cras_reports)) |
| error_msg = ('Active stream count: %d is not matching with ' |
| 'cras active stream count: %d. ' |
| 'Number of cras crashes %d : %s' % |
| (self._active_stream_count, cras_stream_count, |
| len(new_reports), new_reports)) |
| raise error.TestError(error_msg) |
| |
| |
| def collect_cras_crash(self): |
| """Check for cras crashes. |
| |
| @return a list of cras crash reports found. |
| """ |
| |
| crash_reports = [] |
| if not os.path.isdir(_CRASH_PATH): |
| logging.debug('No cras crash detected!') |
| else: |
| cras_reports = os.listdir(_CRASH_PATH) |
| crash_reports = [report for report in cras_reports |
| if report.startswith('cras')] |
| return crash_reports |