1# Copyright (c) 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.
4import subprocess
5from autotest_lib.client.bin import test
6from autotest_lib.client.common_lib import error
7
8
9class platform_Quipper(test.test):
10    """
11    Collects perf data and convert it to a protobuf. Verifies that quipper
12    completes successfully and that the output is nonzero.
13    """
14    version = 1
15
16    def _get_quipper_command(self, duration, perf_options):
17        return ('quipper', str(duration), 'perf', 'record', '-a') + \
18               perf_options
19
20
21    def _get_perf_command(self, duration, perf_options):
22        return ('perf', 'record', '-a') + perf_options + \
23               ('--', 'sleep', str(duration))
24
25
26    def run_once(self):
27        """
28        See test description.
29        """
30
31        duration = 2
32
33        # These are the various perf command options to add to
34        # |quipper_command_base|, for a wide range of commands to test.
35        quipper_command_options = (
36            # Basic cycle-based profile.
37            ('-e', 'cycles'),
38            # Set a custom sampling frequency.
39            ('-e', 'cycles', '-F', '3011'),
40            # Set a custom sampling period.
41            ('-e', 'cycles', '-c', '2000003'),
42            # Test various events.
43            ('-e', 'cycles,instructions,branch-misses,cache-misses'),
44            # Test callgraph.
45            ('-e', 'cycles', '-g'),
46            # Test callgraph and raw data.
47            ('-e', 'cycles', '-g', '-R'),
48            # Test LBR.
49            ('-e', 'cycles', '-b'),
50            # Test LBR, callgraph, and raw data.
51            ('-e', 'cycles', '-b', '-g', '-R'),
52        )
53
54        keyvals = {}
55        # Run quipper with each of the options.
56        for options in quipper_command_options:
57            result = ""
58
59            # Try running the associated perf command first.
60            perf_command = self._get_perf_command(duration, options)
61
62            # Generate a full quipper command by joining the base command
63            # and various perf options.
64            quipper_command = self._get_quipper_command(duration, options)
65            quipper_command_string = ' '.join(quipper_command)
66
67            try:
68                result = subprocess.check_output(perf_command)
69            except subprocess.CalledProcessError:
70                # If the perf command fails, don't test quipper. But record that
71                # it was skipped.
72                keyvals['command'] = '(' + quipper_command_string + ')'
73                keyvals['result_length'] = '(skipped)'
74                self.write_perf_keyval(keyvals)
75                continue
76
77            try:
78                result = subprocess.check_output(quipper_command,
79                                                 stderr=subprocess.STDOUT)
80            except subprocess.CalledProcessError:
81                raise error.TestFail('Error running command: ' +
82                                     quipper_command_string)
83
84            # Write keyvals.
85            keyvals['command'] = quipper_command_string;
86            keyvals['result_length'] = len(result)
87            self.write_perf_keyval(keyvals)
88
89            # Verify the output size.
90            if len(result) == 0:
91                raise error.TestFail('Got no result data from quipper.')
92
93