4bccadd460
Follow up to aosp/2752414 Test: atest-dev auto_gen_test_config_test Change-Id: I401c6213f0ed5e97eb97b1c603a8b6c5286f0d88
140 lines
5.2 KiB
Python
Executable file
140 lines
5.2 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
#
|
|
# Copyright (C) 2017 The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""A tool to generate TradeFed test config file.
|
|
"""
|
|
|
|
import argparse
|
|
import re
|
|
import os
|
|
import shutil
|
|
import sys
|
|
from xml.dom.minidom import parse
|
|
|
|
ATTRIBUTE_LABEL = 'android:label'
|
|
ATTRIBUTE_RUNNER = 'android:name'
|
|
ATTRIBUTE_PACKAGE = 'package'
|
|
|
|
PLACEHOLDER_LABEL = '{LABEL}'
|
|
PLACEHOLDER_EXTRA_CONFIGS = '{EXTRA_CONFIGS}'
|
|
PLACEHOLDER_MODULE = '{MODULE}'
|
|
PLACEHOLDER_PACKAGE = '{PACKAGE}'
|
|
PLACEHOLDER_RUNNER = '{RUNNER}'
|
|
PLACEHOLDER_TEST_TYPE = '{TEST_TYPE}'
|
|
|
|
|
|
def main(argv):
|
|
"""Entry point of auto_gen_test_config.
|
|
|
|
Args:
|
|
argv: A list of arguments.
|
|
Returns:
|
|
0 if no error, otherwise 1.
|
|
"""
|
|
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument(
|
|
"target_config",
|
|
help="Path to the generated output config.")
|
|
parser.add_argument(
|
|
"android_manifest",
|
|
help="Path to AndroidManifest.xml or output of 'aapt2 dump xmltree' with .xmltree extension.")
|
|
parser.add_argument(
|
|
"empty_config",
|
|
help="Path to the empty config template.")
|
|
parser.add_argument(
|
|
"instrumentation_test_config_template",
|
|
help="Path to the instrumentation test config template.")
|
|
parser.add_argument("--extra-configs", default="")
|
|
args = parser.parse_args(argv)
|
|
|
|
target_config = args.target_config
|
|
android_manifest = args.android_manifest
|
|
empty_config = args.empty_config
|
|
instrumentation_test_config_template = args.instrumentation_test_config_template
|
|
extra_configs = '\n'.join(args.extra_configs.split('\\n'))
|
|
|
|
module = os.path.splitext(os.path.basename(target_config))[0]
|
|
|
|
# If the AndroidManifest.xml is not available, but the APK is, this tool also
|
|
# accepts the output of `aapt2 dump xmltree <apk> AndroidManifest.xml` written
|
|
# into a file. This is a custom structured aapt2 output - not raw XML!
|
|
if android_manifest.endswith(".xmltree"):
|
|
label = module
|
|
with open(android_manifest, encoding="utf-8") as manifest:
|
|
# e.g. A: package="android.test.example.helloworld" (Raw: "android.test.example.helloworld")
|
|
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
pattern = re.compile(r"\(Raw:\s\"(.*)\"\)$")
|
|
curr_element = None
|
|
for line in manifest:
|
|
curr_line = line.strip()
|
|
if curr_line.startswith("E:"):
|
|
# e.g. "E: instrumentation (line=9)"
|
|
# ^^^^^^^^^^^^^^^
|
|
curr_element = curr_line.split(" ")[1]
|
|
if curr_element == "instrumentation":
|
|
if ATTRIBUTE_RUNNER in curr_line:
|
|
runner = re.findall(pattern, curr_line)[0]
|
|
if ATTRIBUTE_LABEL in curr_line:
|
|
label = re.findall(pattern, curr_line)[0]
|
|
if curr_element == "manifest":
|
|
if ATTRIBUTE_PACKAGE in curr_line:
|
|
package = re.findall(pattern, curr_line)[0]
|
|
|
|
if not (runner and label and package):
|
|
# Failed to locate instrumentation or manifest element in AndroidManifest.
|
|
# file. Empty test config file will be created.
|
|
shutil.copyfile(empty_config, target_config)
|
|
return 0
|
|
|
|
else:
|
|
# If the AndroidManifest.xml file is directly available, read it as an XML file.
|
|
manifest = parse(android_manifest)
|
|
instrumentation_elements = manifest.getElementsByTagName('instrumentation')
|
|
manifest_elements = manifest.getElementsByTagName('manifest')
|
|
if len(instrumentation_elements) != 1 or len(manifest_elements) != 1:
|
|
# Failed to locate instrumentation or manifest element in AndroidManifest.
|
|
# file. Empty test config file will be created.
|
|
shutil.copyfile(empty_config, target_config)
|
|
return 0
|
|
|
|
instrumentation = instrumentation_elements[0]
|
|
manifest = manifest_elements[0]
|
|
if ATTRIBUTE_LABEL in instrumentation.attributes:
|
|
label = instrumentation.attributes[ATTRIBUTE_LABEL].value
|
|
else:
|
|
label = module
|
|
runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
|
|
package = manifest.attributes[ATTRIBUTE_PACKAGE].value
|
|
|
|
test_type = ('InstrumentationTest'
|
|
if runner.endswith('.InstrumentationTestRunner')
|
|
else 'AndroidJUnitTest')
|
|
|
|
with open(instrumentation_test_config_template) as template:
|
|
config = template.read()
|
|
config = config.replace(PLACEHOLDER_LABEL, label)
|
|
config = config.replace(PLACEHOLDER_MODULE, module)
|
|
config = config.replace(PLACEHOLDER_PACKAGE, package)
|
|
config = config.replace(PLACEHOLDER_TEST_TYPE, test_type)
|
|
config = config.replace(PLACEHOLDER_EXTRA_CONFIGS, extra_configs)
|
|
config = config.replace(PLACEHOLDER_RUNNER, runner)
|
|
with open(target_config, 'w') as config_file:
|
|
config_file.write(config)
|
|
return 0
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main(sys.argv[1:]))
|