xref: /aosp_15_r20/external/autotest/tko/parsers/test/new_scenario.py (revision 9c5db1993ded3edbeafc8092d69fe5de2ee02df7)
1#!/usr/bin/python3
2"""Create new scenario test instance from an existing results directory.
3
4This automates creation of regression tests for the results parsers.
5There are 2 primary use cases for this.
6
71) Bug fixing: Parser broke on some input in the field and we want
8to start with a test that operates on that input and fails. We
9then apply fixes to the parser implementation until it passes.
10
112) Regression alarms: We take input from various real scenarios that
12work as expected with the parser. These will be used to ensure
13we do not break the expected functionality of the parser while
14refactoring it.
15
16While much is done automatically, a scenario harness is meant to
17be easily extended and configured once generated.
18"""
19
20from __future__ import absolute_import
21from __future__ import division
22from __future__ import print_function
23
24import optparse, os, shutil, sys
25from os import path
26
27import common
28from autotest_lib.tko.parsers.test import scenario_base
29from autotest_lib.client.common_lib import autotemp
30
31usage = 'usage: %prog [options] results_dirpath scenerios_dirpath'
32parser = optparse.OptionParser(usage=usage)
33parser.add_option(
34    '-n', '--name',
35    help='Name for new scenario instance. Will use dirname if not specified')
36parser.add_option(
37    '-p', '--parser_result_tag',
38    default='v1',
39    help='Storage tag to use for initial parser result.')
40parser.add_option(
41    '-t', '--template_type',
42    default='base',
43    help='Type of unittest module to copy into new scenario.')
44
45
46def main():
47    (options, args) = parser.parse_args()
48    if len(args) < 2:
49        parser.print_help()
50        sys.exit(1)
51
52    results_dirpath = path.normpath(args[0])
53    if not path.exists(results_dirpath) or not path.isdir(results_dirpath):
54        print('Invalid results_dirpath:', results_dirpath)
55        parser.print_help()
56        sys.exit(1)
57
58    scenarios_dirpath = path.normpath(args[1])
59    if not path.exists(scenarios_dirpath) or not path.isdir(scenarios_dirpath):
60        print('Invalid scenarios_dirpath:', scenarios_dirpath)
61        parser.print_help()
62        sys.exit(1)
63
64    results_dirname = path.basename(results_dirpath)
65    # Not everything is a valid python package name, fix if necessary
66    package_dirname = scenario_base.fix_package_dirname(
67        options.name or results_dirname)
68
69    scenario_package_dirpath = path.join(
70        scenarios_dirpath, package_dirname)
71    if path.exists(scenario_package_dirpath):
72        print(
73            'Scenario package already exists at path: %s' %
74            scenario_package_dirpath)
75        parser.print_help()
76        sys.exit(1)
77
78    # Create new scenario package
79    os.mkdir(scenario_package_dirpath)
80
81    # Create tmp_dir
82    tmp_dirpath = autotemp.tempdir(unique_id='new_scenario')
83    copied_dirpath = path.join(tmp_dirpath.name, results_dirname)
84    # Copy results_dir
85    shutil.copytree(results_dirpath, copied_dirpath)
86
87    # scenario_base.sanitize_results_data(copied_dirpath)
88
89    # Launch parser on copied_dirpath, collect emitted test objects.
90    harness = scenario_base.new_parser_harness(copied_dirpath)
91    try:
92        parser_result = harness.execute()
93    except Exception as e:
94        parser_result = e
95
96    scenario_base.store_parser_result(
97        scenario_package_dirpath, parser_result,
98        options.parser_result_tag)
99
100    scenario_base.store_results_dir(
101        scenario_package_dirpath, copied_dirpath)
102
103    scenario_base.write_config(
104        scenario_package_dirpath,
105        status_version=harness.status_version,
106        parser_result_tag=options.parser_result_tag,
107        )
108
109    scenario_base.install_unittest_module(
110        scenario_package_dirpath, options.template_type)
111    tmp_dirpath.clean()
112
113
114if __name__ == '__main__':
115    main()
116