1# Copyright (c) 2013 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
5import re, errno, logging, utils
6from autotest_lib.client.bin import test
7from autotest_lib.client.common_lib import error
8
9class platform_Mosys(test.test):
10    version = 1
11
12    def __TestAllLeafCommands(self):
13        """Tests all "leaf" sub-commands return non-error.
14
15        Commands that return ENOSYS or EINVAL are not counted as error.
16        Return value are not check for correctness.
17
18        Raises:
19            error.TestFail Raised for commands that return non-zero exit code.
20        """
21
22        # Find all leaf commands by 'mosys -tv'.
23        # Old mosys keeps track root:branch:node numbers; the output for one
24        # command may look like, for example,
25        #    [leaf 5:5] mosys platform variant
26        # Latest mosys removes these numbers:
27        #    [leaf] mosys platform variant
28        cmd_re = re.compile('\[leaf[^\]]*\] (.+)')
29        bad_cmd_list = []
30        cmd_list = utils.system_output('mosys -tv')
31        for line in cmd_list.splitlines():
32            m = cmd_re.search(line)
33            if m and not self.__TestOneCommand(m.group(1)):
34                bad_cmd_list.append(m.group(1))
35
36        if len(bad_cmd_list) == 1:
37            raise error.TestFail('Command not properly implemented: ' +
38                                 bad_cmd_list[0])
39        elif len(bad_cmd_list) > 1:
40            raise error.TestFail('Commands not properly implemented: ' +
41                                 ','.join(bad_cmd_list))
42
43    def __TestOneCommand(self, cmd):
44        """ Tests one "leaf" sub-command.
45
46        Returns
47            True if the command returns 0, ENOSYS or EINVAL; False otherwise.
48        """
49
50        # Note that 'mosys eeprom map' takes about 30 sec to complete on Snow.
51        # We set timeout=40 to accommodate that.
52        result = utils.run(cmd, timeout=40, ignore_status=True)
53        rc = result.exit_status
54        if rc and rc not in [errno.ENOSYS, errno.EINVAL]:
55            # older mosys does not return useful exit code but instead, prints
56            # 'Command not supported on this platform' on stderr or prints
57            # usage info on stdout when the command needs arguments. These are
58            # not considered as error.
59            stderr = result.stderr
60            stdout = result.stdout
61            not_supported = (stderr and
62                stderr.startswith('Command not supported on this platform'))
63            need_argument = stdout and stdout.startswith('usage:')
64            unable_to_determine = (stderr and
65                stderr.startswith('Unable to determine'))
66            if not_supported:
67                logging.info('cmd not supported: "%s"', cmd);
68            elif need_argument:
69                logging.info('cmd needs argument: "%s"', cmd);
70            elif unable_to_determine:
71                logging.info('Unable to determine: "%s"', cmd);
72            else:
73                logging.error('failed to execute "%s"; exit code=%d', cmd, rc);
74                return False
75
76        return True
77
78    def run_once(self):
79        self.__TestAllLeafCommands()
80