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