162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao# Copyright 2016 The Chromium OS Authors. All rights reserved.
262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao# Use of this source code is governed by a BSD-style license that can be
362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao# found in the LICENSE file.
462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoimport logging
662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoimport random
762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoimport re
862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoimport subprocess
962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoimport time
1062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
1162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaofrom autotest_lib.client.bin import test
1262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaofrom autotest_lib.client.common_lib import error
1362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
1462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
1562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chaoclass audio_CrasOutputStress(test.test):
1662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    """Checks if output buffer will drift to super high level."""
1762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    version = 1
1862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    _MAX_OUTPUT_STREAMS = 3
1962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    _LOOP_COUNT = 300
2062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    _OUTPUT_BUFFER_LEVEL = '.*?SET_DEV_WAKE.*?hw_level.*?(\d+).*?'
2162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    _BUFFER_DRIFT_CRITERIA = 4096
2262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
2362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    def run_once(self):
2462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        """
2562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        Repeatedly add output streams of random configurations and
2662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        remove them to verify if output buffer level would drift.
2762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        """
2862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        self._output_streams = []
2962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        self._rates = ['48000', '44100']
3062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        self._block_sizes = ['512', '1024']
3162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
3262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        loop_count = 0
3362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        while loop_count < self._LOOP_COUNT:
3462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            if len(self._output_streams) < self._MAX_OUTPUT_STREAMS:
3562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                cmd = ['cras_test_client', '--playback_file', '/dev/zero',
3662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                       '--rate', self._rates[random.randint(0, 1)],
3762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                       '--block_size', self._block_sizes[random.randint(0, 1)]]
3862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                proc = subprocess.Popen(cmd)
3962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                self._output_streams.append(proc)
4062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                time.sleep(0.01)
4162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            else:
4262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                self._output_streams[0].kill()
4362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                self._output_streams.remove(self._output_streams[0])
4462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                time.sleep(0.1)
4562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            loop_count += 1
4662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
4762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        # Get the buffer level.
4862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        buffer_level = self._get_buffer_level()
4962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
5062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        # Clean up all streams.
5162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        while len(self._output_streams) > 0:
5262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            self._output_streams[0].kill()
5362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            self._output_streams.remove(self._output_streams[0])
5462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
5562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        if buffer_level > self._BUFFER_DRIFT_CRITERIA:
5662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            raise error.TestFail('Buffer level %d drift too high', buffer_level)
5762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
5862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao    def _get_buffer_level(self):
5962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        """Gets a rough number about current buffer level.
6062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
6162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        @returns: The current buffer level.
6262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
6362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        """
6462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        proc = subprocess.Popen(['cras_test_client', '--dump_a'], stdout=subprocess.PIPE)
6562bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        output, err = proc.communicate()
6662bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        buffer_level = 0
6762bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        for line in output.split('\n'):
6862bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            search = re.match(self._OUTPUT_BUFFER_LEVEL, line)
6962bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao            if search:
7062bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                tmp = int(search.group(1))
7162bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                if tmp > buffer_level:
7262bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao                    buffer_level = tmp
7362bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao        return buffer_level
7462bf1f449b0c4a5f2d1c9e6a357f362ca4df5f48Hsin-Yu Chao
75