• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python
2# Copyright 2018 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Fake implementation of tast executable used by tast_unittest.py.
7
8In unit tests, this file is executed instead of the real tast executable by the
9tast.py server test. It:
10
11- reads a config.json file installed alongside this script,
12- parses command-line arguments passed by tast.py,
13- checks that the arguments included all required args specified by the config
14  file for the given command (e.g. 'list', 'run' etc.), and
15- performs actions specified by the config file.
16"""
17
18import argparse
19import json
20import os
21import sys
22
23
24def main():
25    # pylint: disable=missing-docstring
26
27    # The config file is written by TastTest._run_test in tast_unittest.py and
28    # consists of a dict from command names (e.g. 'list', 'run', etc.) to
29    # command definition dicts (see TastCommand in tast_unittest.py).
30    path = os.path.join(os.path.dirname(os.path.realpath(__file__)),
31                        'config.json')
32    with open(path) as f:
33        cfg = json.load(f)
34
35    args = parse_args()
36    cmd = cfg.get(args.command)
37    if not cmd:
38        raise RuntimeError('Unexpected command "%s"' % args.command)
39
40    for arg in cmd.get('required_args', []):
41        name, expected_value = arg.split('=')
42        # argparse puts the repeated "pattern" args into a list of lists
43        # instead of a single list. Pull the args back out in this case.
44        val = getattr(args, name)
45        if isinstance(val, list) and len(val) == 1 and isinstance(val[0], list):
46            val = val[0]
47        actual_value = str(val)
48        if actual_value != expected_value:
49            raise RuntimeError('Got arg %s with value "%s"; want "%s"' %
50                               (name, actual_value, expected_value))
51
52    if cmd.get('stdout'):
53        sys.stdout.write(cmd['stdout'])
54    if cmd.get('stderr'):
55        sys.stderr.write(cmd['stderr'])
56
57    if cmd.get('files_to_write'):
58        for path, data in cmd['files_to_write'].iteritems():
59            dirname = os.path.dirname(path)
60            if not os.path.exists(dirname):
61                os.makedirs(dirname, 0755)
62            with open(path, 'w') as f:
63                f.write(data)
64
65    sys.exit(cmd.get('status'))
66
67
68def parse_args():
69    """Parses command-line arguments.
70
71    @returns: argparse.Namespace object containing parsed attributes.
72    """
73    def to_bool(v):
74        """Converts a boolean flag's value to a Python bool value."""
75        if v == 'true' or v == '':
76            return True
77        if v == 'false':
78            return False
79        raise argparse.ArgumentTypeError('"true" or "false" expected')
80
81    parser = argparse.ArgumentParser()
82    parser.add_argument('-logtime', type=to_bool, default=False, nargs='?')
83    parser.add_argument('-verbose', type=to_bool, default=False, nargs='?')
84    parser.add_argument('-version', action='version', version='1.0')
85
86    subparsers = parser.add_subparsers(dest='command')
87
88    def add_common_args(subparser):
89        """Adds arguments shared between tast's 'list' and 'run' subcommands."""
90        subparser.add_argument('-build', type=to_bool, default=True, nargs='?')
91        subparser.add_argument('-downloadprivatebundles', type=to_bool,
92                               default=False, nargs='?')
93        subparser.add_argument('-devservers')
94        subparser.add_argument('-remotebundledir')
95        subparser.add_argument('-remotedatadir')
96        subparser.add_argument('-remoterunner')
97        subparser.add_argument('-sshretries')
98        subparser.add_argument('target')
99        subparser.add_argument('patterns', action='append', nargs='*')
100
101    list_parser = subparsers.add_parser('list')
102    add_common_args(list_parser)
103    list_parser.add_argument('-json', type=to_bool, default=False, nargs='?')
104
105    run_parser = subparsers.add_parser('run')
106    add_common_args(run_parser)
107    run_parser.add_argument('-resultsdir')
108    run_parser.add_argument('-waituntilready')
109    run_parser.add_argument('-timeout')
110
111    return parser.parse_args()
112
113
114if __name__ == '__main__':
115    main()
116