Auto generate test config files
This change allows one to run atest <module name>. The TradeFed test
config file will be automatically created in testcases directory based
on the settings.
Bug: 69929803, 69932044
Test: m -j NotificationStressTests libminijail_test
add following lines in notificationtests/Android.mk,
before "include $(BUILD_PACKAGE)"
LOCAL_COMPATIBILITY_SUITE := general-test
Change-Id: Ib5e9cd152d957b5d5beb6ed23a899a021a7e06d6
diff --git a/tools/auto_gen_test_config.py b/tools/auto_gen_test_config.py
new file mode 100755
index 0000000..fa018f4
--- /dev/null
+++ b/tools/auto_gen_test_config.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# 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 os
+import shutil
+import sys
+from xml.dom.minidom import parse
+
+ATTRIBUTE_LABEL = 'android:label'
+ATTRIBUTE_RUNNER = 'android:name'
+ATTRIBUTE_TARGET_PACKAGE = 'android:targetPackage'
+
+PLACEHOLDER_LABEL = '{LABEL}'
+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.
+ """
+ if len(argv) != 4:
+ sys.stderr.write(
+ 'Invalid arguements. The script requires 4 arguments for file paths: '
+ 'target_config android_manifest empty_config '
+ 'instrumentation_test_config_template.\n')
+ return 1
+ target_config = argv[0]
+ android_manifest = argv[1]
+ empty_config = argv[2]
+ instrumentation_test_config_template = argv[3]
+
+ manifest = parse(android_manifest)
+ instrumentation_elements = manifest.getElementsByTagName('instrumentation')
+ if len(instrumentation_elements) != 1:
+ # Failed to locate instrumentation element in AndroidManifest file.
+ # Empty test config file will be created.
+ shutil.copyfile(empty_config, target_config)
+ return 0
+
+ module = os.path.splitext(os.path.basename(target_config))[0]
+ instrumentation = instrumentation_elements[0]
+ if instrumentation.attributes.has_key(ATTRIBUTE_LABEL):
+ label = instrumentation.attributes[ATTRIBUTE_LABEL].value
+ else:
+ label = module
+ runner = instrumentation.attributes[ATTRIBUTE_RUNNER].value
+ package = instrumentation.attributes[ATTRIBUTE_TARGET_PACKAGE].value
+ test_type = ('AndroidJUnitTest' if runner.endswith('.AndroidJUnitRunner')
+ else 'InstrumentationTest')
+
+ 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_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:]))
diff --git a/tools/auto_gen_test_config_test.py b/tools/auto_gen_test_config_test.py
new file mode 100644
index 0000000..a438b73
--- /dev/null
+++ b/tools/auto_gen_test_config_test.py
@@ -0,0 +1,170 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+
+"""Unittests for auto_gen_test_config."""
+
+import os
+import shutil
+import tempfile
+import unittest
+
+import auto_gen_test_config
+
+TEST_MODULE = 'TestModule'
+
+MANIFEST_INVALID = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+</manifest>
+"""
+
+MANIFEST_JUNIT_TEST = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <instrumentation
+ android:name="android.support.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.my.tests" />
+</manifest>
+"""
+
+MANIFEST_INSTRUMENTATION_TEST = """<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android">
+ <instrumentation
+ android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.android.my.tests"
+ android:label="My Tests" />
+</manifest>
+"""
+
+EXPECTED_JUNIT_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs TestModule.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="TestModule.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.my.tests" />
+ <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+ </test>
+</configuration>
+"""
+
+EXPECTED_INSTRUMENTATION_TEST_CONFIG = """<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<!-- This test config file is auto-generated. -->
+<configuration description="Runs My Tests.">
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="test-file-name" value="TestModule.apk" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.InstrumentationTest" >
+ <option name="package" value="com.android.my.tests" />
+ <option name="runner" value="android.test.InstrumentationTestRunner" />
+ </test>
+</configuration>
+"""
+
+MAKE_ROOT = os.path.dirname(os.path.dirname(__file__))
+EMPTY_TEST_CONFIG = os.path.join(MAKE_ROOT, 'core', 'empty_test_config.xml')
+INSTRUMENTATION_TEST_CONFIG_TEMPLATE = os.path.join(
+ MAKE_ROOT, 'core', 'instrumentation_test_config_template.xml')
+
+
+class AutoGenTestConfigUnittests(unittest.TestCase):
+ """Unittests for auto_gen_test_config."""
+
+ def setUp(self):
+ """Setup directory for test."""
+ self.test_dir = tempfile.mkdtemp()
+ self.config_file = os.path.join(self.test_dir, TEST_MODULE + '.config')
+ self.manifest_file = os.path.join(self.test_dir, 'AndroidManifest.xml')
+
+ def tearDown(self):
+ """Cleanup the test directory."""
+ shutil.rmtree(self.test_dir, ignore_errors=True)
+
+ def testInvalidManifest(self):
+ """An empty test config should be generated if AndroidManifest is invalid.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INVALID)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ with open(EMPTY_TEST_CONFIG) as empty_config:
+ self.assertEqual(config_file.read(), empty_config.read())
+
+ def testCreateJUnitTestConfig(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_JUNIT_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(config_file.read(), EXPECTED_JUNIT_TEST_CONFIG)
+
+ def testCreateInstrumentationTestConfig(self):
+ """Test creating test config for AndroidJUnitTest.
+ """
+ with open(self.manifest_file, 'w') as f:
+ f.write(MANIFEST_INSTRUMENTATION_TEST)
+
+ argv = [self.config_file,
+ self.manifest_file,
+ EMPTY_TEST_CONFIG,
+ INSTRUMENTATION_TEST_CONFIG_TEMPLATE]
+ auto_gen_test_config.main(argv)
+ with open(self.config_file) as config_file:
+ self.assertEqual(
+ config_file.read(), EXPECTED_INSTRUMENTATION_TEST_CONFIG)
+
+if __name__ == '__main__':
+ unittest.main()