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 time
      9 
     10 from autotest_lib.client.bin import test
     11 from autotest_lib.client.common_lib.cros import chrome
     12 from autotest_lib.client.common_lib import error
     13 from 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 
     23 class 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