From e5cd4e10a070b75d4dd04b4c21e12c3f6943a424 Mon Sep 17 00:00:00 2001 From: Jaewoong Jung Date: Fri, 22 Nov 2019 14:34:55 -0800 Subject: [PATCH] Optionally overwrite package value in test config. If package_name is set for an android_test module, package names in its AndroidTest.xml config need to be updated too. Test: test_config_fixer_test.py Fixes: 145011263 Change-Id: I52f17ef1d1902364b9bcfec4f6e246bd655dbf09 --- java/app.go | 11 +++++ scripts/Android.bp | 36 ++++++++++++++ scripts/manifest.py | 11 ++++- scripts/test_config_fixer.py | 82 +++++++++++++++++++++++++++++++ scripts/test_config_fixer_test.py | 71 ++++++++++++++++++++++++++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100644 scripts/test_config_fixer.py create mode 100644 scripts/test_config_fixer_test.py diff --git a/java/app.go b/java/app.go index c63570366..b693ce951 100644 --- a/java/app.go +++ b/java/app.go @@ -632,6 +632,17 @@ func (a *AndroidTest) GenerateAndroidBuildActions(ctx android.ModuleContext) { a.testConfig = tradefed.AutoGenInstrumentationTestConfig(ctx, a.testProperties.Test_config, a.testProperties.Test_config_template, a.manifestPath, a.testProperties.Test_suites, a.testProperties.Auto_gen_config) + if a.overridableAppProperties.Package_name != nil { + fixedConfig := android.PathForModuleOut(ctx, "test_config_fixer", "AndroidTest.xml") + rule := android.NewRuleBuilder() + rule.Command().BuiltTool(ctx, "test_config_fixer"). + FlagWithArg("--manifest ", a.manifestPath.String()). + FlagWithArg("--package-name ", *a.overridableAppProperties.Package_name). + Input(a.testConfig). + Output(fixedConfig) + rule.Build(pctx, ctx, "fix_test_config", "fix test config") + a.testConfig = fixedConfig + } a.data = android.PathsForModuleSrc(ctx, a.testProperties.Data) } diff --git a/scripts/Android.bp b/scripts/Android.bp index 8c59cbc58..4aaff9ae2 100644 --- a/scripts/Android.bp +++ b/scripts/Android.bp @@ -85,3 +85,39 @@ python_binary_host { }, } } + +python_binary_host { + name: "test_config_fixer", + main: "test_config_fixer.py", + srcs: [ + "test_config_fixer.py", + "manifest.py", + ], + version: { + py2: { + enabled: true, + }, + py3: { + enabled: false, + }, + }, +} + +python_test_host { + name: "test_config_fixer_test", + main: "test_config_fixer_test.py", + srcs: [ + "test_config_fixer_test.py", + "test_config_fixer.py", + "manifest.py", + ], + version: { + py2: { + enabled: true, + }, + py3: { + enabled: false, + }, + }, + test_suites: ["general-tests"], +} \ No newline at end of file diff --git a/scripts/manifest.py b/scripts/manifest.py index 4c75f8bf2..04f7405df 100755 --- a/scripts/manifest.py +++ b/scripts/manifest.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # -"""A tool for inserting values from the build system into a manifest.""" +"""A tool for inserting values from the build system into a manifest or a test config.""" from __future__ import print_function from xml.dom import minidom @@ -65,6 +65,15 @@ def ensure_manifest_android_ns(doc): ns.value) +def parse_test_config(doc): + """ Get the configuration element. """ + + test_config = doc.documentElement + if test_config.tagName != 'configuration': + raise RuntimeError('expected configuration tag at root') + return test_config + + def as_int(s): try: i = int(s) diff --git a/scripts/test_config_fixer.py b/scripts/test_config_fixer.py new file mode 100644 index 000000000..7bb4b52a3 --- /dev/null +++ b/scripts/test_config_fixer.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 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 for modifying values in a test config.""" + +from __future__ import print_function + +import argparse +import sys +from xml.dom import minidom + + +from manifest import get_children_with_tag +from manifest import parse_manifest +from manifest import parse_test_config +from manifest import write_xml + + +def parse_args(): + """Parse commandline arguments.""" + + parser = argparse.ArgumentParser() + parser.add_argument('--manifest', default='', dest='manifest', + help=('AndroidManifest.xml that contains the original package name')) + parser.add_argument('--package-name', default='', dest='package_name', + help=('overwrite package fields in the test config')) + parser.add_argument('input', help='input test config file') + parser.add_argument('output', help='output test config file') + return parser.parse_args() + + +def overwrite_package_name(test_config_doc, manifest_doc, package_name): + + manifest = parse_manifest(manifest_doc) + original_package = manifest.getAttribute('package') + print('package: ' + original_package) + + test_config = parse_test_config(test_config_doc) + tests = get_children_with_tag(test_config, 'test') + + for test in tests: + options = get_children_with_tag(test, 'option') + for option in options: + if option.getAttribute('name') == "package" and option.getAttribute('value') == original_package: + option.setAttribute('value', package_name) + +def main(): + """Program entry point.""" + try: + args = parse_args() + + doc = minidom.parse(args.input) + + if args.package_name: + if not args.manifest: + raise RuntimeError('--manifest flag required for --package-name') + manifest_doc = minidom.parse(args.manifest) + overwrite_package_name(doc, manifest_doc, args.package_name) + + with open(args.output, 'wb') as f: + write_xml(f, doc) + + # pylint: disable=broad-except + except Exception as err: + print('error: ' + str(err), file=sys.stderr) + sys.exit(-1) + +if __name__ == '__main__': + main() diff --git a/scripts/test_config_fixer_test.py b/scripts/test_config_fixer_test.py new file mode 100644 index 000000000..b90582ed9 --- /dev/null +++ b/scripts/test_config_fixer_test.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python +# +# Copyright (C) 2019 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. +# +"""Unit tests for test_config_fixer.py.""" + +import StringIO +import sys +import unittest +from xml.dom import minidom + +import test_config_fixer + +sys.dont_write_bytecode = True + + +class OverwritePackageNameTest(unittest.TestCase): + """ Unit tests for overwrite_package_name function """ + + manifest = ( + '\n' + '\n' + ' \n' + ' \n' + '\n') + + test_config = ( + '\n' + '\n' + ' \n') + + def test_all(self): + doc = minidom.parseString(self.test_config % ("com.android.foo", "com.android.foo", "com.android.bar")) + manifest = minidom.parseString(self.manifest) + + test_config_fixer.overwrite_package_name(doc, manifest, "com.soong.foo") + output = StringIO.StringIO() + test_config_fixer.write_xml(output, doc) + + # Only the matching package name in a test node should be updated. + expected = self.test_config % ("com.android.foo", "com.soong.foo", "com.android.bar") + self.assertEqual(expected, output.getvalue()) + + +if __name__ == '__main__': + unittest.main(verbosity=2)