Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 1 | #!/usr/bin/env python |
| 2 | # |
| 3 | # Copyright (C) 2019 The Android Open Source Project |
| 4 | # |
| 5 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | # you may not use this file except in compliance with the License. |
| 7 | # You may obtain a copy of the License at |
| 8 | # |
| 9 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | # |
| 11 | # Unless required by applicable law or agreed to in writing, software |
| 12 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | # See the License for the specific language governing permissions and |
| 15 | # limitations under the License. |
| 16 | # |
| 17 | """A tool for modifying values in a test config.""" |
| 18 | |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 19 | import argparse |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 20 | import json |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 21 | import sys |
| 22 | from xml.dom import minidom |
| 23 | |
| 24 | |
| 25 | from manifest import get_children_with_tag |
| 26 | from manifest import parse_manifest |
| 27 | from manifest import parse_test_config |
| 28 | from manifest import write_xml |
| 29 | |
Rahul Sabnis | 48a8f0d | 2022-04-19 18:00:10 -0700 | [diff] [blame] | 30 | KNOWN_PREPARERS = ['com.android.tradefed.targetprep.TestAppInstallSetup', |
| 31 | 'com.android.tradefed.targetprep.suite.SuiteApkInstaller'] |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 32 | |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 33 | KNOWN_TEST_RUNNERS = ['com.android.tradefed.testtype.AndroidJUnitTest'] |
| 34 | |
Seth Moore | c6f4b53 | 2023-02-02 13:22:26 -0800 | [diff] [blame] | 35 | MAINLINE_CONTROLLER = 'com.android.tradefed.testtype.suite.module.MainlineTestModuleController' |
| 36 | |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 37 | def parse_args(): |
| 38 | """Parse commandline arguments.""" |
| 39 | |
| 40 | parser = argparse.ArgumentParser() |
| 41 | parser.add_argument('--manifest', default='', dest='manifest', |
| 42 | help=('AndroidManifest.xml that contains the original package name')) |
| 43 | parser.add_argument('--package-name', default='', dest='package_name', |
| 44 | help=('overwrite package fields in the test config')) |
Jaewoong Jung | 3998234 | 2020-01-14 10:27:18 -0800 | [diff] [blame] | 45 | parser.add_argument('--test-file-name', default='', dest='test_file_name', |
| 46 | help=('overwrite test file name in the test config')) |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 47 | parser.add_argument('--orig-test-file-name', default='', dest='orig_test_file_name', |
| 48 | help=('Use with test-file-name to only override a single apk')) |
Seth Moore | c6f4b53 | 2023-02-02 13:22:26 -0800 | [diff] [blame] | 49 | parser.add_argument('--mainline-package-name', default='', dest='mainline_package_name', |
| 50 | help=('overwrite mainline module package name in the test config')) |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 51 | parser.add_argument('--test-runner-options', default='', dest='test_runner_options', |
| 52 | help=('Add test runner options in the test config')) |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 53 | parser.add_argument('input', help='input test config file') |
| 54 | parser.add_argument('output', help='output test config file') |
| 55 | return parser.parse_args() |
| 56 | |
| 57 | |
| 58 | def overwrite_package_name(test_config_doc, manifest_doc, package_name): |
| 59 | |
| 60 | manifest = parse_manifest(manifest_doc) |
| 61 | original_package = manifest.getAttribute('package') |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 62 | |
| 63 | test_config = parse_test_config(test_config_doc) |
| 64 | tests = get_children_with_tag(test_config, 'test') |
| 65 | |
| 66 | for test in tests: |
| 67 | options = get_children_with_tag(test, 'option') |
| 68 | for option in options: |
| 69 | if option.getAttribute('name') == "package" and option.getAttribute('value') == original_package: |
| 70 | option.setAttribute('value', package_name) |
| 71 | |
Jaewoong Jung | 3998234 | 2020-01-14 10:27:18 -0800 | [diff] [blame] | 72 | def overwrite_test_file_name(test_config_doc, test_file_name): |
| 73 | |
| 74 | test_config = parse_test_config(test_config_doc) |
| 75 | tests = get_children_with_tag(test_config, 'target_preparer') |
| 76 | |
| 77 | for test in tests: |
Rahul Sabnis | 48a8f0d | 2022-04-19 18:00:10 -0700 | [diff] [blame] | 78 | if test.getAttribute('class') in KNOWN_PREPARERS: |
Jaewoong Jung | 3998234 | 2020-01-14 10:27:18 -0800 | [diff] [blame] | 79 | options = get_children_with_tag(test, 'option') |
| 80 | for option in options: |
| 81 | if option.getAttribute('name') == "test-file-name": |
| 82 | option.setAttribute('value', test_file_name) |
| 83 | |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 84 | def overwrite_single_test_file_name(test_config_doc, orig_test_file_name, new_test_file_name): |
| 85 | |
| 86 | test_config = parse_test_config(test_config_doc) |
| 87 | tests = get_children_with_tag(test_config, 'target_preparer') |
| 88 | |
| 89 | for test in tests: |
| 90 | if test.getAttribute('class') in KNOWN_PREPARERS: |
| 91 | options = get_children_with_tag(test, 'option') |
| 92 | for option in options: |
| 93 | if option.getAttribute('name') == "test-file-name" and option.getAttribute('value') == orig_test_file_name: |
| 94 | option.setAttribute('value', new_test_file_name) |
| 95 | |
Seth Moore | c6f4b53 | 2023-02-02 13:22:26 -0800 | [diff] [blame] | 96 | def overwrite_mainline_module_package_name(test_config_doc, mainline_package_name): |
| 97 | |
| 98 | test_config = parse_test_config(test_config_doc) |
| 99 | |
| 100 | for obj in get_children_with_tag(test_config, 'object'): |
| 101 | if obj.getAttribute('class') == MAINLINE_CONTROLLER: |
| 102 | for option in get_children_with_tag(obj, 'option'): |
| 103 | if option.getAttribute('name') == "mainline-module-package-name": |
| 104 | option.setAttribute('value', mainline_package_name) |
| 105 | |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 106 | def add_test_runner_options_toplevel(test_config_doc, test_runner_options): |
| 107 | |
| 108 | test_config = parse_test_config(test_config_doc) |
| 109 | |
| 110 | test_config.appendChild(test_config_doc.createComment("Options from Android.bp")) |
| 111 | test_config.appendChild(test_config_doc.createTextNode("\n")) |
| 112 | for new_option in json.loads(test_runner_options): |
| 113 | option = test_config_doc.createElement("option") |
| 114 | # name and value are mandatory, |
| 115 | name = new_option.get('Name') |
| 116 | if not name: |
| 117 | raise RuntimeError('"name" must set in test_runner_option"') |
| 118 | value = new_option.get('Value') |
| 119 | if not value: |
| 120 | raise RuntimeError('"value" must set in test_runner_option"') |
| 121 | option.setAttribute('name', name) # 'include-filter') |
| 122 | option.setAttribute('value', value) # 'android.test.example.devcodelab.DevCodelabTest#testHelloFail') |
| 123 | key = new_option.get('Key') |
| 124 | if key: |
| 125 | option.setAttribute('key', key) # 'include-filter') |
| 126 | # add tab and newline for readability |
| 127 | test_config.appendChild(test_config_doc.createTextNode(" ")) |
| 128 | test_config.appendChild(option) |
| 129 | test_config.appendChild(test_config_doc.createTextNode("\n")) |
| 130 | |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 131 | def main(): |
| 132 | """Program entry point.""" |
| 133 | try: |
| 134 | args = parse_args() |
| 135 | |
| 136 | doc = minidom.parse(args.input) |
| 137 | |
| 138 | if args.package_name: |
| 139 | if not args.manifest: |
| 140 | raise RuntimeError('--manifest flag required for --package-name') |
| 141 | manifest_doc = minidom.parse(args.manifest) |
| 142 | overwrite_package_name(doc, manifest_doc, args.package_name) |
| 143 | |
Jaewoong Jung | 3998234 | 2020-01-14 10:27:18 -0800 | [diff] [blame] | 144 | if args.test_file_name: |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 145 | if args.orig_test_file_name: |
| 146 | overwrite_single_test_file_name(doc, args.orig_test_file_name, args.test_file_name) |
| 147 | else: |
| 148 | # You probably never want to override the test_file_name if there |
| 149 | # are several in the xml, but this is currently only used on generated |
| 150 | # AndroidTest.xml where there is only a single test-file-name (no data) |
| 151 | overwrite_test_file_name(doc, args.test_file_name) |
Jaewoong Jung | 3998234 | 2020-01-14 10:27:18 -0800 | [diff] [blame] | 152 | |
Seth Moore | c6f4b53 | 2023-02-02 13:22:26 -0800 | [diff] [blame] | 153 | if args.mainline_package_name: |
| 154 | overwrite_mainline_module_package_name(doc, args.mainline_package_name) |
| 155 | |
Ronald Braunstein | fce4316 | 2024-02-02 12:37:20 -0800 | [diff] [blame] | 156 | if args.test_runner_options: |
| 157 | add_test_runner_options_toplevel(doc, args.test_runner_options) |
| 158 | |
Cole Faust | c41dd72 | 2021-11-09 15:08:26 -0800 | [diff] [blame] | 159 | with open(args.output, 'w') as f: |
Jaewoong Jung | e5cd4e1 | 2019-11-22 14:34:55 -0800 | [diff] [blame] | 160 | write_xml(f, doc) |
| 161 | |
| 162 | # pylint: disable=broad-except |
| 163 | except Exception as err: |
| 164 | print('error: ' + str(err), file=sys.stderr) |
| 165 | sys.exit(-1) |
| 166 | |
| 167 | if __name__ == '__main__': |
| 168 | main() |