blob: 8a50f8a4ea3b31204f30962bd77c3ef38d263d36 [file] [log] [blame]
Kevin Cheng8b2c94c2017-12-18 14:43:26 -08001# Copyright 2018, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""
16Test Finder Handler module.
17"""
18
mikehoran8bf6d082018-02-26 16:22:06 -080019import logging
20
Kevin Cheng8b2c94c2017-12-18 14:43:26 -080021import atest_enum
22from test_finders import test_finder_base
23from test_finders import tf_integration_finder
24from test_finders import module_finder
25
26# List of default test finder classes.
27_TEST_FINDERS = {
28 tf_integration_finder.TFIntegrationFinder,
29 module_finder.ModuleFinder,
30}
31
32# Explanation of REFERENCE_TYPEs:
33# ----------------------------------
34# 0. MODULE: LOCAL_MODULE or LOCAL_PACKAGE_NAME value in Android.mk/Android.bp.
35# 1. MODULE_CLASS: Combo of MODULE and CLASS as "module:class".
36# 2. PACKAGE: package in java file. Same as file path to java file.
37# 3. MODULE_PACKAGE: Combo of MODULE and PACKAGE as "module:package".
38# 4. MODULE_FILE_PATH: File path to dir of tests or test itself.
39# 5. INTEGRATION_FILE_PATH: File path to config xml in one of the 4 integration
40# config directories.
41# 6. INTEGRATION: xml file name in one of the 4 integration config directories.
42# 7. SUITE: Value of the "run-suite-tag" in xml config file in 4 config dirs.
43# Same as value of "test-suite-tag" in AndroidTest.xml files.
44_REFERENCE_TYPE = atest_enum.AtestEnum(['MODULE', 'CLASS', 'QUALIFIED_CLASS',
45 'MODULE_CLASS', 'PACKAGE',
46 'MODULE_PACKAGE', 'MODULE_FILE_PATH',
47 'INTEGRATION_FILE_PATH', 'INTEGRATION',
48 'SUITE'])
49
50_REF_TYPE_TO_FUNC_MAP = {
51 _REFERENCE_TYPE.MODULE: module_finder.ModuleFinder.find_test_by_module_name,
52 _REFERENCE_TYPE.CLASS: module_finder.ModuleFinder.find_test_by_class_name,
53 _REFERENCE_TYPE.MODULE_CLASS: module_finder.ModuleFinder.find_test_by_module_and_class,
54 _REFERENCE_TYPE.QUALIFIED_CLASS: module_finder.ModuleFinder.find_test_by_class_name,
mikehoran6740a412018-02-20 15:04:16 -080055 _REFERENCE_TYPE.PACKAGE: module_finder.ModuleFinder.find_test_by_package_name,
56 _REFERENCE_TYPE.MODULE_PACKAGE: module_finder.ModuleFinder.find_test_by_module_and_package,
Kevin Cheng8b2c94c2017-12-18 14:43:26 -080057 _REFERENCE_TYPE.MODULE_FILE_PATH: module_finder.ModuleFinder.find_test_by_path,
58 _REFERENCE_TYPE.INTEGRATION_FILE_PATH:
59 tf_integration_finder.TFIntegrationFinder.find_int_test_by_path,
60 _REFERENCE_TYPE.INTEGRATION:
61 tf_integration_finder.TFIntegrationFinder.find_test_by_integration_name,
62}
63
64
65def _get_finder_instance_dict(module_info):
66 """Return dict of finder instances.
67
68 Args:
69 module_info: ModuleInfo for finder classes to use.
70
71 Returns:
72 Dict of finder instances keyed by their name.
73 """
74 instance_dict = {}
75 for finder in _get_test_finders():
76 instance_dict[finder.NAME] = finder(module_info=module_info)
77 return instance_dict
78
79
80def _get_test_finders():
81 """Returns the test finders.
82
83 If external test types are defined outside atest, they can be try-except
84 imported into here.
85
86 Returns:
87 Set of test finder classes.
88 """
89 test_finders_list = _TEST_FINDERS
90 # Example import of external test finder:
91 try:
92 from test_finders import example_finder
93 test_finders_list.add(example_finder.ExampleFinder)
94 except ImportError:
95 pass
96 return test_finders_list
97
mikehoran6740a412018-02-20 15:04:16 -080098# pylint: disable=too-many-return-statements
Kevin Cheng8b2c94c2017-12-18 14:43:26 -080099def _get_test_reference_types(ref):
100 """Determine type of test reference based on the content of string.
101
102 Examples:
103 The string 'SequentialRWTest' could be a reference to
104 a Module or a Class name.
105
106 The string 'cts/tests/filesystem' could be a Path, Integration
107 or Suite reference.
108
109 Args:
110 ref: A string referencing a test.
111
112 Returns:
113 A list of possible REFERENCE_TYPEs (ints) for reference string.
114 """
115 if ref.startswith('.') or '..' in ref:
116 return [_REFERENCE_TYPE.INTEGRATION_FILE_PATH,
117 _REFERENCE_TYPE.MODULE_FILE_PATH]
118 if '/' in ref:
119 if ref.startswith('/'):
120 return [_REFERENCE_TYPE.INTEGRATION_FILE_PATH,
121 _REFERENCE_TYPE.MODULE_FILE_PATH]
122 return [_REFERENCE_TYPE.INTEGRATION_FILE_PATH,
123 _REFERENCE_TYPE.MODULE_FILE_PATH,
124 _REFERENCE_TYPE.INTEGRATION,
Kevin Chengdd8fba12018-02-20 10:17:33 -0800125 # TODO: Comment in SUITE when it's supported
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800126 # _REFERENCE_TYPE.SUITE
127 ]
mikehoran6740a412018-02-20 15:04:16 -0800128 if '.' in ref:
129 ref_end = ref.rsplit('.', 1)[-1]
130 ref_end_is_upper = ref_end[0].isupper()
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800131 if ':' in ref:
132 if '.' in ref:
mikehoran6740a412018-02-20 15:04:16 -0800133 if ref_end_is_upper:
134 # Module:fully.qualified.Class or Integration:fully.q.Class
135 return [_REFERENCE_TYPE.INTEGRATION,
136 _REFERENCE_TYPE.MODULE_CLASS]
137 # Module:some.package
138 return [_REFERENCE_TYPE.MODULE_PACKAGE]
139 # Module:Class or IntegrationName:Class
140 return [_REFERENCE_TYPE.INTEGRATION,
141 _REFERENCE_TYPE.MODULE_CLASS]
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800142 if '.' in ref:
mikehoran6740a412018-02-20 15:04:16 -0800143 if ref_end in ('java', 'bp', 'mk'):
144 return [_REFERENCE_TYPE.MODULE_FILE_PATH]
145 if ref_end == 'xml':
146 return [_REFERENCE_TYPE.INTEGRATION_FILE_PATH]
147 if ref_end_is_upper:
148 return [_REFERENCE_TYPE.QUALIFIED_CLASS]
149 return [_REFERENCE_TYPE.PACKAGE]
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800150 # Note: We assume that if you're referencing a file in your cwd,
151 # that file must have a '.' in its name, i.e. foo.java, foo.xml.
152 # If this ever becomes not the case, then we need to include path below.
153 return [_REFERENCE_TYPE.INTEGRATION,
Kevin Chengdd8fba12018-02-20 10:17:33 -0800154 # TODO: Comment in SUITE when it's supported
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800155 # REFERENCE_TYPE.SUITE,
156 _REFERENCE_TYPE.MODULE,
157 _REFERENCE_TYPE.CLASS]
158
159
160def _get_registered_find_methods(module_info):
161 """Return list of registered find methods.
162
163 This is used to return find methods that were not listed in the
164 default find methods but just registered in the finder classes. These
165 find methods will run before the default find methods.
166
167 Args:
168 module_info: ModuleInfo for finder classes to instantiate with.
169
170 Returns:
171 List of registered find methods.
172 """
173 find_methods = []
174 finder_instance_dict = _get_finder_instance_dict(module_info)
175 for finder in _get_test_finders():
176 finder_instance = finder_instance_dict[finder.NAME]
177 for find_method_info in finder_instance.get_all_find_methods():
178 find_methods.append(test_finder_base.Finder(
179 finder_instance, find_method_info.find_method))
180 return find_methods
181
182
183def _get_default_find_methods(module_info, test):
184 """Default find methods to be used based on the given test name.
185
186 Args:
187 module_info: ModuleInfo for finder instances to use.
188 test: String of test name to help determine which find methods
189 to utilize.
190
191 Returns:
192 List of find methods to use.
193 """
194 find_methods = []
195 finder_instance_dict = _get_finder_instance_dict(module_info)
mikehoran8bf6d082018-02-26 16:22:06 -0800196 test_ref_types = _get_test_reference_types(test)
197 logging.debug('Resolved input to possible references: %s', [
198 _REFERENCE_TYPE[t] for t in test_ref_types])
199 for test_ref_type in test_ref_types:
Kevin Chengdd8fba12018-02-20 10:17:33 -0800200 find_method = _REF_TYPE_TO_FUNC_MAP[test_ref_type]
201 finder_instance = finder_instance_dict[find_method.im_class.NAME]
202 find_methods.append(test_finder_base.Finder(finder_instance,
203 find_method))
Kevin Cheng8b2c94c2017-12-18 14:43:26 -0800204 return find_methods
205
206
207def get_find_methods_for_test(module_info, test):
208 """Return a list of ordered find methods.
209
210 Args:
211 test: String of test name to get find methods for.
212
213 Returns:
214 List of ordered find methods.
215 """
216 registered_find_methods = _get_registered_find_methods(module_info)
217 default_find_methods = _get_default_find_methods(module_info, test)
218 return registered_find_methods + default_find_methods