普通文本  |  142行  |  5.55 KB

# 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 shutil
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() 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