xref: /aosp_15_r20/external/autotest/utils/generate_metadata.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1#!/usr/bin/python3
2# Copyright (c) 2021 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"""Generate metadata for build from Autotest ctrl files."""
6
7import argparse
8import os
9import six
10import sys
11
12# If running in Autotest dir, keep this.
13os.environ["PY_VERSION"] = '3'
14
15import common
16
17# NOTE: this MUST be run in Python3, if we get configured back to PY2, exit.
18if six.PY2:
19    exit(1)
20
21from autotest_lib.server.cros.dynamic_suite import control_file_getter
22from autotest_lib.client.common_lib import control_data
23
24from chromiumos.test.api import test_case_metadata_pb2 as tc_metadata_pb
25from chromiumos.test.api import test_harness_pb2 as th_pb
26from chromiumos.test.api import test_case_pb2 as tc_pb
27
28HARNESS = th_pb.TestHarness.Tauto()
29
30
31def parse_local_arguments(args):
32    """Parse the CLI."""
33    parser = argparse.ArgumentParser(
34            description="Prep Autotest, Tast, & Services for DockerBuild.")
35    parser.add_argument('-autotest_path',
36                        dest='autotest_path',
37                        default='../../../../third_party/autotest/files/',
38                        help='path to autotest/files relative to this script.')
39    parser.add_argument('-output_file',
40                        dest='output_file',
41                        default=None,
42                        help='Where to write the serialized pb.')
43    return parser.parse_args(args)
44
45
46def read_file(filename):
47    """Read the given file."""
48    with open(filename, 'r') as f:
49        return f.read()
50
51
52def all_control_files(args):
53    """Return all control files as control file objs."""
54    subpaths = ['server/site_tests', 'client/site_tests']
55    start_cwd = os.getcwd()
56    try:
57        os.chdir(args.autotest_path)
58
59        # Might not be needed, but this resolves out the ../
60        autotest_path = os.getcwd()
61
62        directories = [os.path.join(autotest_path, p) for p in subpaths]
63        f = control_file_getter.FileSystemGetter(directories)
64    except Exception as e:
65        raise Exception("Failed to find control files at path %s",
66                        args.autotest_path)
67
68    finally:
69        os.chdir(start_cwd)
70    return f._get_control_file_list()
71
72
73def serialize_test_case_info(data):
74    """Return a serialized TestCaseInfo obj."""
75    serialized_contacts = tc_metadata_pb.Contact(email=data.author)
76    return tc_metadata_pb.TestCaseInfo(owners=[serialized_contacts])
77
78
79def serialize_tags(data):
80    """Return a serialized tags obj (list)."""
81    serialized_tags = []
82    for value in data.dependencies:
83        serialized_tags.append(tc_pb.TestCase.Tag(value=value))
84    for value in data.attributes:
85        serialized_tags.append(tc_pb.TestCase.Tag(value=value))
86    if data.test_class:
87        serialized_tags.append(
88                tc_pb.TestCase.Tag(
89                        value="test_class:{}".format(data.test_class)))
90    return serialized_tags
91
92
93def serialize_test_case(data):
94    """Return a serialized api.TestCase obj."""
95    serialized_testcase_id = tc_pb.TestCase.Id(value="tauto." + data.name)
96    tags = serialize_tags(data)
97    return tc_pb.TestCase(id=serialized_testcase_id, name=data.name, tags=tags)
98
99
100def serialized_test_case_exec(data):
101    """Return a serialized TestCaseExec obj."""
102    serialized_test_harness = th_pb.TestHarness(tauto=HARNESS)
103    return tc_metadata_pb.TestCaseExec(test_harness=serialized_test_harness)
104
105
106def serialized_test_case_metadata(data):
107    """Return a TestCaseMetadata obj from a given control file."""
108    serialized_meta_data = tc_metadata_pb.TestCaseMetadata(
109            test_case_exec=serialized_test_case_exec(data),
110            test_case=serialize_test_case(data),
111            test_case_info=serialize_test_case_info(data))
112    return serialized_meta_data
113
114
115def serialized_test_case_metadata_list(data):
116    """Return a TestCaseMetadataList obj from a list of TestCaseMetadata pb."""
117    serialized_meta_data_list = tc_metadata_pb.TestCaseMetadataList(
118            values=data)
119    return serialized_meta_data_list
120
121
122def main():
123    """Generate the metadata, and if an output path is given, save it."""
124    args = parse_local_arguments(sys.argv[1:])
125    ctrlfiles = all_control_files(args)
126    serialized_metadata = []
127    for file_path in ctrlfiles:
128        text = read_file(file_path)
129        path = ctrlfiles[1]
130
131        test = control_data.parse_control_string(text,
132                                                 raise_warnings=True,
133                                                 path=path)
134        serialized_metadata.append(serialized_test_case_metadata(test))
135
136    serialized = serialized_test_case_metadata_list(serialized_metadata)
137    if args.output_file:
138        with open(args.output_file, 'wb') as wf:
139            wf.write(serialized.SerializeToString())
140
141
142if __name__ == '__main__':
143    main()
144