Merge "Auto generate test config files" am: 3c28ff7bff

am: 4ccd1a5a00

Change-Id: Ibc089081ab2925f8e3453eddf8c64d81d3b49596
This commit is contained in:
Dan Shi 2017-12-21 22:25:40 +00:00 committed by android-build-merger
commit 26201a4d44
9 changed files with 425 additions and 5 deletions

View File

@ -0,0 +1,60 @@
#
# 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 build rule allows TradeFed test config file to be created based on
# following inputs:
# is_native: If the test is a native test.
# LOCAL_MANIFEST_FILE: Name of the AndroidManifest file for the test. If it's
# not set, default value `AndroidManifest.xml` will be used.
# Output:
# autogen_test_config_file: Path to the test config file generated.
autogen_test_config_file := $(dir $(LOCAL_BUILT_MODULE))$(LOCAL_MODULE).config
ifeq (true,$(is_native))
# Auto generating test config file for native test
$(autogen_test_config_file) : $(NATIVE_TEST_CONFIG_TEMPLATE)
@echo "Auto generating test config $(notdir $@)"
$(hide) sed 's&{MODULE}&$(PRIVATE_MODULE)&g' $^ > $@
my_auto_generate_config := true
else
# Auto generating test config file for instrumentation test
ifeq ($(strip $(LOCAL_MANIFEST_FILE)),)
LOCAL_MANIFEST_FILE := AndroidManifest.xml
endif
ifdef LOCAL_FULL_MANIFEST_FILE
my_android_manifest := $(LOCAL_FULL_MANIFEST_FILE)
else
my_android_manifest := $(LOCAL_PATH)/$(LOCAL_MANIFEST_FILE)
endif
ifneq (,$(wildcard $(my_android_manifest)))
$(autogen_test_config_file) : $(my_android_manifest) $(EMPTY_TEST_CONFIG) $(INSTRUMENTATION_TEST_CONFIG_TEMPLATE)
@echo "Auto generating test config $(notdir $@)"
@rm -f $@
$(hide) $(AUTOGEN_TEST_CONFIG_SCRIPT) $@ $^
my_auto_generate_config := true
endif # ifeq (,$(wildcard $(my_android_manifest)))
endif # ifneq (true,$(is_native))
ifeq (true,$(my_auto_generate_config))
LOCAL_INTERMEDIATE_TARGETS += $(autogen_test_config_file)
$(LOCAL_BUILT_MODULE): $(autogen_test_config_file)
ALL_MODULES.$(my_register_name).auto_test_config := true
else
autogen_test_config_file :=
endif
my_android_manifest :=
my_auto_generate_config :=

View File

@ -510,7 +510,6 @@ ifdef LOCAL_MULTILIB
endif
ifdef is_native
arch_dir := /$($(my_prefix)$(LOCAL_2ND_ARCH_VAR_PREFIX)ARCH)
is_native :=
endif
# The module itself.
@ -531,13 +530,35 @@ $(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
$(s):$(dir)/$(n)))))
test_config := $(wildcard $(LOCAL_PATH)/AndroidTest.xml)
ifeq (,$(test_config))
ifneq (true,$(is_native))
is_instrumentation_test := true
ifeq (true, $(LOCAL_IS_HOST_MODULE))
is_instrumentation_test := false
endif
endif
# CTS modules can be used for test data, so test config files must be
# explicitly created using AndroidTest.xml
ifeq (,$(filter cts, $(LOCAL_COMPATIBILITY_SUITE)))
ifeq (true, $(filter true,$(is_native) $(is_instrumentation_test)))
include $(BUILD_SYSTEM)/autogen_test_config.mk
test_config := $(autogen_test_config_file)
autogen_test_config_file :=
endif
endif
endif
ifneq (,$(wildcard $(LOCAL_PATH)/AndroidTest.xml))
is_instrumentation_test :=
ifneq (,$(test_config))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
$(LOCAL_PATH)/AndroidTest.xml:$(dir)/$(LOCAL_MODULE).config)))
$(test_config):$(dir)/$(LOCAL_MODULE).config)))
endif
test_config :=
ifneq (,$(wildcard $(LOCAL_PATH)/DynamicConfig.xml))
$(foreach suite, $(LOCAL_COMPATIBILITY_SUITE), \
$(eval my_compat_dist_$(suite) += $(foreach dir, $(call compatibility_suite_dirs,$(suite)), \
@ -552,6 +573,9 @@ $(foreach extra_config, $(wildcard $(LOCAL_PATH)/$(LOCAL_MODULE)_*.config), \
endif
endif # $(my_prefix)$(LOCAL_MODULE_CLASS)_$(LOCAL_MODULE)_compat_files
arch_dir :=
is_native :=
ifneq ($(my_test_data_file_pairs),)
$(foreach pair, $(my_test_data_file_pairs), \
$(eval parts := $(subst :,$(space),$(pair))) \

View File

@ -156,8 +156,15 @@ BUILD_NOTICE_FILE := $(BUILD_SYSTEM)/notice_files.mk
BUILD_HOST_DALVIK_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_java_library.mk
BUILD_HOST_DALVIK_STATIC_JAVA_LIBRARY := $(BUILD_SYSTEM)/host_dalvik_static_java_library.mk
BUILD_HOST_TEST_CONFIG:= $(BUILD_SYSTEM)/host_test_config.mk
BUILD_TARGET_TEST_CONFIG:= $(BUILD_SYSTEM)/target_test_config.mk
BUILD_HOST_TEST_CONFIG := $(BUILD_SYSTEM)/host_test_config.mk
BUILD_TARGET_TEST_CONFIG := $(BUILD_SYSTEM)/target_test_config.mk
INSTRUMENTATION_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/instrumentation_test_config_template.xml
NATIVE_TEST_CONFIG_TEMPLATE := $(BUILD_SYSTEM)/native_test_config_template.xml
EMPTY_TEST_CONFIG := $(BUILD_SYSTEM)/empty_test_config.xml
# Tool to generate TradeFed test config file automatically.
AUTOGEN_TEST_CONFIG_SCRIPT := build/make/tools/auto_gen_test_config.py
# ###############################################################
# Parse out any modifier targets.

View File

@ -0,0 +1,19 @@
<?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.
-->
<!-- No AndroidTest.xml was provided and the manifest does not include
instrumentation, hence this apk is not instrumentable.
-->
<configuration description="Empty Configuration" />

View File

@ -0,0 +1,26 @@
<?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 {LABEL}.">
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="test-file-name" value="{MODULE}.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.{TEST_TYPE}" >
<option name="package" value="{PACKAGE}" />
<option name="runner" value="{RUNNER}" />
</test>
</configuration>

View File

@ -0,0 +1,27 @@
<?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 {MODULE}.">
<target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
<option name="cleanup" value="true" />
<option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
</target_preparer>
<test class="com.android.tradefed.testtype.GTest" >
<option name="native-test-device-path" value="/data/local/tmp" />
<option name="module-name" value="{MODULE}" />
</test>
</configuration>

View File

@ -12,6 +12,7 @@ $(MODULE_INFO_JSON):
'"tags": [$(foreach w,$(sort $(ALL_MODULES.$(m).TAGS)),"$(w)", )], ' \
'"installed": [$(foreach w,$(sort $(ALL_MODULES.$(m).INSTALLED)),"$(w)", )], ' \
'"compatibility_suites": [$(foreach w,$(sort $(ALL_MODULES.$(m).COMPATIBILITY_SUITES)),"$(w)", )], ' \
'"auto_test_config": [$(ALL_MODULES.$(m).auto_test_config)], ' \
'},\n' \
) | sed -e 's/, *\]/]/g' -e 's/, *\}/ }/g' -e '$$s/,$$//' >> $@
$(hide) echo '}' >> $@

86
tools/auto_gen_test_config.py Executable file
View File

@ -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:]))

View File

@ -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()