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