xref: /aosp_15_r20/tools/asuite/atest/test_finders/module_finder.py (revision c2e18aaa1096c836b086f94603d04f4eb9cf37f5)
1*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2018, The Android Open Source Project
2*c2e18aaaSAndroid Build Coastguard Worker#
3*c2e18aaaSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*c2e18aaaSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*c2e18aaaSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*c2e18aaaSAndroid Build Coastguard Worker#
7*c2e18aaaSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*c2e18aaaSAndroid Build Coastguard Worker#
9*c2e18aaaSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*c2e18aaaSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*c2e18aaaSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*c2e18aaaSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*c2e18aaaSAndroid Build Coastguard Worker# limitations under the License.
14*c2e18aaaSAndroid Build Coastguard Worker
15*c2e18aaaSAndroid Build Coastguard Worker"""Module Finder class."""
16*c2e18aaaSAndroid Build Coastguard Worker
17*c2e18aaaSAndroid Build Coastguard Workerimport logging
18*c2e18aaaSAndroid Build Coastguard Workerimport os
19*c2e18aaaSAndroid Build Coastguard Workerimport time
20*c2e18aaaSAndroid Build Coastguard Workerfrom typing import List
21*c2e18aaaSAndroid Build Coastguard Worker
22*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_configs
23*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_error
24*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils
25*c2e18aaaSAndroid Build Coastguard Workerfrom atest import constants
26*c2e18aaaSAndroid Build Coastguard Workerfrom atest.atest_enum import DetectType
27*c2e18aaaSAndroid Build Coastguard Workerfrom atest.metrics import metrics
28*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_filter_utils
29*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_finder_base
30*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_finder_utils
31*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_info
32*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_runners import atest_tf_test_runner
33*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_runners import mobly_test_runner
34*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_runners import robolectric_test_runner
35*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_runners import vts_tf_test_runner
36*c2e18aaaSAndroid Build Coastguard Worker
37*c2e18aaaSAndroid Build Coastguard Worker# These are suites in LOCAL_COMPATIBILITY_SUITE that aren't really suites so
38*c2e18aaaSAndroid Build Coastguard Worker# we can ignore them.
39*c2e18aaaSAndroid Build Coastguard Worker_SUITES_TO_IGNORE = frozenset({'general-tests', 'device-tests', 'tests'})
40*c2e18aaaSAndroid Build Coastguard Worker
41*c2e18aaaSAndroid Build Coastguard Worker
42*c2e18aaaSAndroid Build Coastguard Workerclass ModuleFinder(test_finder_base.TestFinderBase):
43*c2e18aaaSAndroid Build Coastguard Worker  """Module finder class."""
44*c2e18aaaSAndroid Build Coastguard Worker
45*c2e18aaaSAndroid Build Coastguard Worker  NAME = 'MODULE'
46*c2e18aaaSAndroid Build Coastguard Worker  _TEST_RUNNER = atest_tf_test_runner.AtestTradefedTestRunner.NAME
47*c2e18aaaSAndroid Build Coastguard Worker  _MOBLY_RUNNER = mobly_test_runner.MoblyTestRunner.NAME
48*c2e18aaaSAndroid Build Coastguard Worker  _ROBOLECTRIC_RUNNER = robolectric_test_runner.RobolectricTestRunner.NAME
49*c2e18aaaSAndroid Build Coastguard Worker  _VTS_TEST_RUNNER = vts_tf_test_runner.VtsTradefedTestRunner.NAME
50*c2e18aaaSAndroid Build Coastguard Worker
51*c2e18aaaSAndroid Build Coastguard Worker  def __init__(self, module_info=None):
52*c2e18aaaSAndroid Build Coastguard Worker    super().__init__()
53*c2e18aaaSAndroid Build Coastguard Worker    self.root_dir = os.environ.get(constants.ANDROID_BUILD_TOP)
54*c2e18aaaSAndroid Build Coastguard Worker    self.module_info = module_info
55*c2e18aaaSAndroid Build Coastguard Worker
56*c2e18aaaSAndroid Build Coastguard Worker  def _determine_modules_to_test(
57*c2e18aaaSAndroid Build Coastguard Worker      self, module_path: str, test_file_path: str = None
58*c2e18aaaSAndroid Build Coastguard Worker  ) -> set[str]:
59*c2e18aaaSAndroid Build Coastguard Worker    """Determine which module the user is trying to test.
60*c2e18aaaSAndroid Build Coastguard Worker
61*c2e18aaaSAndroid Build Coastguard Worker    Returns the modules to test. If there are multiple possibilities, will
62*c2e18aaaSAndroid Build Coastguard Worker    ask the user. Otherwise will return the only module found.
63*c2e18aaaSAndroid Build Coastguard Worker
64*c2e18aaaSAndroid Build Coastguard Worker    Args:
65*c2e18aaaSAndroid Build Coastguard Worker        module_path: String path of module to look for.
66*c2e18aaaSAndroid Build Coastguard Worker        test_file_path: String path of input file where the test is found.
67*c2e18aaaSAndroid Build Coastguard Worker
68*c2e18aaaSAndroid Build Coastguard Worker    Returns:
69*c2e18aaaSAndroid Build Coastguard Worker        A set of the module names.
70*c2e18aaaSAndroid Build Coastguard Worker    """
71*c2e18aaaSAndroid Build Coastguard Worker    modules_to_test = set()
72*c2e18aaaSAndroid Build Coastguard Worker
73*c2e18aaaSAndroid Build Coastguard Worker    if test_file_path:
74*c2e18aaaSAndroid Build Coastguard Worker      modules_to_test = self.module_info.get_modules_by_path_in_srcs(
75*c2e18aaaSAndroid Build Coastguard Worker          path=test_file_path,
76*c2e18aaaSAndroid Build Coastguard Worker          testable_modules_only=True,
77*c2e18aaaSAndroid Build Coastguard Worker      )
78*c2e18aaaSAndroid Build Coastguard Worker
79*c2e18aaaSAndroid Build Coastguard Worker    # If a single module path matches contains the path of the given test file
80*c2e18aaaSAndroid Build Coastguard Worker    # in its MODULE_SRCS, do not continue to extract modules.
81*c2e18aaaSAndroid Build Coastguard Worker    if len(modules_to_test) == 1:
82*c2e18aaaSAndroid Build Coastguard Worker      return modules_to_test
83*c2e18aaaSAndroid Build Coastguard Worker
84*c2e18aaaSAndroid Build Coastguard Worker    modules_to_test |= self.module_info.get_modules_by_path(
85*c2e18aaaSAndroid Build Coastguard Worker        path=module_path,
86*c2e18aaaSAndroid Build Coastguard Worker        testable_modules_only=True,
87*c2e18aaaSAndroid Build Coastguard Worker    )
88*c2e18aaaSAndroid Build Coastguard Worker
89*c2e18aaaSAndroid Build Coastguard Worker    return test_finder_utils.extract_selected_tests(modules_to_test)
90*c2e18aaaSAndroid Build Coastguard Worker
91*c2e18aaaSAndroid Build Coastguard Worker  def _is_vts_module(self, module_name):
92*c2e18aaaSAndroid Build Coastguard Worker    """Returns True if the module is a vts10 module, else False."""
93*c2e18aaaSAndroid Build Coastguard Worker    mod_info = self.module_info.get_module_info(module_name)
94*c2e18aaaSAndroid Build Coastguard Worker    suites = []
95*c2e18aaaSAndroid Build Coastguard Worker    if mod_info:
96*c2e18aaaSAndroid Build Coastguard Worker      suites = mod_info.get(constants.MODULE_COMPATIBILITY_SUITES, [])
97*c2e18aaaSAndroid Build Coastguard Worker    # Pull out all *ts (cts, tvts, etc) suites.
98*c2e18aaaSAndroid Build Coastguard Worker    suites = [suite for suite in suites if suite not in _SUITES_TO_IGNORE]
99*c2e18aaaSAndroid Build Coastguard Worker    return len(suites) == 1 and 'vts10' in suites
100*c2e18aaaSAndroid Build Coastguard Worker
101*c2e18aaaSAndroid Build Coastguard Worker  def _update_to_vts_test_info(self, test):
102*c2e18aaaSAndroid Build Coastguard Worker    """Fill in the fields with vts10 specific info.
103*c2e18aaaSAndroid Build Coastguard Worker
104*c2e18aaaSAndroid Build Coastguard Worker    We need to update the runner to use the vts10 runner and also find the
105*c2e18aaaSAndroid Build Coastguard Worker    test specific dependencies.
106*c2e18aaaSAndroid Build Coastguard Worker
107*c2e18aaaSAndroid Build Coastguard Worker    Args:
108*c2e18aaaSAndroid Build Coastguard Worker        test: TestInfo to update with vts10 specific details.
109*c2e18aaaSAndroid Build Coastguard Worker
110*c2e18aaaSAndroid Build Coastguard Worker    Returns:
111*c2e18aaaSAndroid Build Coastguard Worker        TestInfo that is ready for the vts10 test runner.
112*c2e18aaaSAndroid Build Coastguard Worker    """
113*c2e18aaaSAndroid Build Coastguard Worker    test.test_runner = self._VTS_TEST_RUNNER
114*c2e18aaaSAndroid Build Coastguard Worker    config_file = os.path.join(
115*c2e18aaaSAndroid Build Coastguard Worker        self.root_dir, test.data[constants.TI_REL_CONFIG]
116*c2e18aaaSAndroid Build Coastguard Worker    )
117*c2e18aaaSAndroid Build Coastguard Worker    # Need to get out dir (special logic is to account for custom out dirs).
118*c2e18aaaSAndroid Build Coastguard Worker    # The out dir is used to construct the build targets for the test deps.
119*c2e18aaaSAndroid Build Coastguard Worker    out_dir = os.environ.get(constants.ANDROID_HOST_OUT)
120*c2e18aaaSAndroid Build Coastguard Worker    custom_out_dir = os.environ.get(constants.ANDROID_OUT_DIR)
121*c2e18aaaSAndroid Build Coastguard Worker    # If we're not an absolute custom out dir, get no-absolute out dir path.
122*c2e18aaaSAndroid Build Coastguard Worker    if custom_out_dir is None or not os.path.isabs(custom_out_dir):
123*c2e18aaaSAndroid Build Coastguard Worker      out_dir = os.path.relpath(out_dir, self.root_dir)
124*c2e18aaaSAndroid Build Coastguard Worker    vts_out_dir = os.path.join(out_dir, 'vts10', 'android-vts10', 'testcases')
125*c2e18aaaSAndroid Build Coastguard Worker    # Parse dependency of default staging plans.
126*c2e18aaaSAndroid Build Coastguard Worker    xml_paths = test_finder_utils.search_integration_dirs(
127*c2e18aaaSAndroid Build Coastguard Worker        constants.VTS_STAGING_PLAN,
128*c2e18aaaSAndroid Build Coastguard Worker        self.module_info.get_paths(constants.VTS_TF_MODULE),
129*c2e18aaaSAndroid Build Coastguard Worker    )
130*c2e18aaaSAndroid Build Coastguard Worker    vts_xmls = set()
131*c2e18aaaSAndroid Build Coastguard Worker    vts_xmls.add(config_file)
132*c2e18aaaSAndroid Build Coastguard Worker    for xml_path in xml_paths:
133*c2e18aaaSAndroid Build Coastguard Worker      vts_xmls |= test_finder_utils.get_plans_from_vts_xml(xml_path)
134*c2e18aaaSAndroid Build Coastguard Worker    for config_file in vts_xmls:
135*c2e18aaaSAndroid Build Coastguard Worker      # Add in vts10 test build targets.
136*c2e18aaaSAndroid Build Coastguard Worker      for target in test_finder_utils.get_targets_from_vts_xml(
137*c2e18aaaSAndroid Build Coastguard Worker          config_file, vts_out_dir, self.module_info
138*c2e18aaaSAndroid Build Coastguard Worker      ):
139*c2e18aaaSAndroid Build Coastguard Worker        test.add_build_target(target)
140*c2e18aaaSAndroid Build Coastguard Worker    test.add_build_target('vts-test-core')
141*c2e18aaaSAndroid Build Coastguard Worker    test.add_build_target(test.test_name)
142*c2e18aaaSAndroid Build Coastguard Worker    return test
143*c2e18aaaSAndroid Build Coastguard Worker
144*c2e18aaaSAndroid Build Coastguard Worker  def _update_to_mobly_test_info(self, test):
145*c2e18aaaSAndroid Build Coastguard Worker    """Update the fields for a Mobly test.
146*c2e18aaaSAndroid Build Coastguard Worker
147*c2e18aaaSAndroid Build Coastguard Worker    The runner will be updated to the Mobly runner.
148*c2e18aaaSAndroid Build Coastguard Worker
149*c2e18aaaSAndroid Build Coastguard Worker    The module's build output paths will be stored in the test_info data.
150*c2e18aaaSAndroid Build Coastguard Worker
151*c2e18aaaSAndroid Build Coastguard Worker    Args:
152*c2e18aaaSAndroid Build Coastguard Worker        test: TestInfo to be updated with Mobly fields.
153*c2e18aaaSAndroid Build Coastguard Worker
154*c2e18aaaSAndroid Build Coastguard Worker    Returns:
155*c2e18aaaSAndroid Build Coastguard Worker        TestInfo with updated Mobly fields.
156*c2e18aaaSAndroid Build Coastguard Worker    """
157*c2e18aaaSAndroid Build Coastguard Worker    # Set test runner to MoblyTestRunner
158*c2e18aaaSAndroid Build Coastguard Worker    test.test_runner = self._MOBLY_RUNNER
159*c2e18aaaSAndroid Build Coastguard Worker    # Add test module as build target
160*c2e18aaaSAndroid Build Coastguard Worker    module_name = test.test_name
161*c2e18aaaSAndroid Build Coastguard Worker    test.add_build_target(module_name)
162*c2e18aaaSAndroid Build Coastguard Worker    # Add module's installed paths to data, so the runner may access the
163*c2e18aaaSAndroid Build Coastguard Worker    # module's build outputs.
164*c2e18aaaSAndroid Build Coastguard Worker    installed_paths = self.module_info.get_installed_paths(module_name)
165*c2e18aaaSAndroid Build Coastguard Worker    test.data[constants.MODULE_INSTALLED] = installed_paths
166*c2e18aaaSAndroid Build Coastguard Worker    return test
167*c2e18aaaSAndroid Build Coastguard Worker
168*c2e18aaaSAndroid Build Coastguard Worker  def _update_legacy_robolectric_test_info(self, test):
169*c2e18aaaSAndroid Build Coastguard Worker    """Update the fields for a legacy robolectric test.
170*c2e18aaaSAndroid Build Coastguard Worker
171*c2e18aaaSAndroid Build Coastguard Worker    This method is updating test_name when the given is a legacy robolectric
172*c2e18aaaSAndroid Build Coastguard Worker    test, and assigning Robolectric Runner for it.
173*c2e18aaaSAndroid Build Coastguard Worker
174*c2e18aaaSAndroid Build Coastguard Worker    e.g. WallPaperPicker2RoboTests is a legacy robotest, and the test_name
175*c2e18aaaSAndroid Build Coastguard Worker    will become RunWallPaperPicker2RoboTests and run it with Robolectric
176*c2e18aaaSAndroid Build Coastguard Worker    Runner.
177*c2e18aaaSAndroid Build Coastguard Worker
178*c2e18aaaSAndroid Build Coastguard Worker    Args:
179*c2e18aaaSAndroid Build Coastguard Worker        test: TestInfo to be updated with robolectric fields.
180*c2e18aaaSAndroid Build Coastguard Worker
181*c2e18aaaSAndroid Build Coastguard Worker    Returns:
182*c2e18aaaSAndroid Build Coastguard Worker        TestInfo with updated robolectric fields.
183*c2e18aaaSAndroid Build Coastguard Worker    """
184*c2e18aaaSAndroid Build Coastguard Worker    test.test_runner = self._ROBOLECTRIC_RUNNER
185*c2e18aaaSAndroid Build Coastguard Worker    test.test_name = self.module_info.get_robolectric_test_name(
186*c2e18aaaSAndroid Build Coastguard Worker        self.module_info.get_module_info(test.test_name)
187*c2e18aaaSAndroid Build Coastguard Worker    )
188*c2e18aaaSAndroid Build Coastguard Worker    return test
189*c2e18aaaSAndroid Build Coastguard Worker
190*c2e18aaaSAndroid Build Coastguard Worker  # pylint: disable=too-many-branches
191*c2e18aaaSAndroid Build Coastguard Worker  def _process_test_info(self, test):
192*c2e18aaaSAndroid Build Coastguard Worker    """Process the test info and return some fields updated/changed.
193*c2e18aaaSAndroid Build Coastguard Worker
194*c2e18aaaSAndroid Build Coastguard Worker    We need to check if the test found is a special module (like vts10) and
195*c2e18aaaSAndroid Build Coastguard Worker    update the test_info fields (like test_runner) appropriately.
196*c2e18aaaSAndroid Build Coastguard Worker
197*c2e18aaaSAndroid Build Coastguard Worker    Args:
198*c2e18aaaSAndroid Build Coastguard Worker        test: TestInfo that has been filled out by a find method.
199*c2e18aaaSAndroid Build Coastguard Worker
200*c2e18aaaSAndroid Build Coastguard Worker    Returns:
201*c2e18aaaSAndroid Build Coastguard Worker        TestInfo that has been modified as needed and return None if
202*c2e18aaaSAndroid Build Coastguard Worker        this module can't be found in the module_info.
203*c2e18aaaSAndroid Build Coastguard Worker    """
204*c2e18aaaSAndroid Build Coastguard Worker    module_name = test.test_name
205*c2e18aaaSAndroid Build Coastguard Worker    mod_info = self.module_info.get_module_info(module_name)
206*c2e18aaaSAndroid Build Coastguard Worker    if not mod_info:
207*c2e18aaaSAndroid Build Coastguard Worker      return None
208*c2e18aaaSAndroid Build Coastguard Worker    test.module_class = mod_info['class']
209*c2e18aaaSAndroid Build Coastguard Worker    test.install_locations = test_finder_utils.get_install_locations(
210*c2e18aaaSAndroid Build Coastguard Worker        mod_info.get(constants.MODULE_INSTALLED, [])
211*c2e18aaaSAndroid Build Coastguard Worker    )
212*c2e18aaaSAndroid Build Coastguard Worker    # Check if this is only a vts10 module.
213*c2e18aaaSAndroid Build Coastguard Worker    if self._is_vts_module(test.test_name):
214*c2e18aaaSAndroid Build Coastguard Worker      return self._update_to_vts_test_info(test)
215*c2e18aaaSAndroid Build Coastguard Worker    # Check if this is a Mobly test module.
216*c2e18aaaSAndroid Build Coastguard Worker    if self.module_info.is_mobly_module(mod_info):
217*c2e18aaaSAndroid Build Coastguard Worker      return self._update_to_mobly_test_info(test)
218*c2e18aaaSAndroid Build Coastguard Worker    test.robo_type = self.module_info.get_robolectric_type(test.test_name)
219*c2e18aaaSAndroid Build Coastguard Worker    if test.robo_type:
220*c2e18aaaSAndroid Build Coastguard Worker      test.install_locations = {constants.DEVICELESS_TEST}
221*c2e18aaaSAndroid Build Coastguard Worker      if test.robo_type == constants.ROBOTYPE_MODERN:
222*c2e18aaaSAndroid Build Coastguard Worker        test.add_build_target(test.test_name)
223*c2e18aaaSAndroid Build Coastguard Worker        return test
224*c2e18aaaSAndroid Build Coastguard Worker      if test.robo_type == constants.ROBOTYPE_LEGACY:
225*c2e18aaaSAndroid Build Coastguard Worker        return self._update_legacy_robolectric_test_info(test)
226*c2e18aaaSAndroid Build Coastguard Worker    rel_config = test.data[constants.TI_REL_CONFIG]
227*c2e18aaaSAndroid Build Coastguard Worker    for target in self._get_build_targets(module_name, rel_config):
228*c2e18aaaSAndroid Build Coastguard Worker      test.add_build_target(target)
229*c2e18aaaSAndroid Build Coastguard Worker    # (b/177626045) Probe target APK for running instrumentation tests to
230*c2e18aaaSAndroid Build Coastguard Worker    # prevent RUNNER ERROR by adding target application(module) to the
231*c2e18aaaSAndroid Build Coastguard Worker    # build_targets, and install these target apks before testing.
232*c2e18aaaSAndroid Build Coastguard Worker    artifact_map = self.module_info.get_instrumentation_target_apps(module_name)
233*c2e18aaaSAndroid Build Coastguard Worker    if artifact_map:
234*c2e18aaaSAndroid Build Coastguard Worker      logging.debug('Found %s an instrumentation test.', module_name)
235*c2e18aaaSAndroid Build Coastguard Worker      for art in artifact_map.keys():
236*c2e18aaaSAndroid Build Coastguard Worker        test.add_build_target(art)
237*c2e18aaaSAndroid Build Coastguard Worker      logging.debug(
238*c2e18aaaSAndroid Build Coastguard Worker          'Add %s to build targets...', ', '.join(artifact_map.keys())
239*c2e18aaaSAndroid Build Coastguard Worker      )
240*c2e18aaaSAndroid Build Coastguard Worker      test.artifacts = []
241*c2e18aaaSAndroid Build Coastguard Worker      for p in artifact_map.values():
242*c2e18aaaSAndroid Build Coastguard Worker        test.artifacts += p
243*c2e18aaaSAndroid Build Coastguard Worker      logging.debug('Will install target APK: %s\n', test.artifacts)
244*c2e18aaaSAndroid Build Coastguard Worker      metrics.LocalDetectEvent(
245*c2e18aaaSAndroid Build Coastguard Worker          detect_type=DetectType.FOUND_TARGET_ARTIFACTS,
246*c2e18aaaSAndroid Build Coastguard Worker          result=len(test.artifacts),
247*c2e18aaaSAndroid Build Coastguard Worker      )
248*c2e18aaaSAndroid Build Coastguard Worker    # For device side java test, it will use
249*c2e18aaaSAndroid Build Coastguard Worker    # com.android.compatibility.testtype.DalvikTest as test runner in
250*c2e18aaaSAndroid Build Coastguard Worker    # cts-dalvik-device-test-runner.jar
251*c2e18aaaSAndroid Build Coastguard Worker    if self.module_info.is_auto_gen_test_config(module_name):
252*c2e18aaaSAndroid Build Coastguard Worker      if constants.MODULE_CLASS_JAVA_LIBRARIES in test.module_class:
253*c2e18aaaSAndroid Build Coastguard Worker        for dalvik_dep in test_finder_utils.DALVIK_TEST_DEPS:
254*c2e18aaaSAndroid Build Coastguard Worker          if self.module_info.is_module(dalvik_dep):
255*c2e18aaaSAndroid Build Coastguard Worker            test.add_build_target(dalvik_dep)
256*c2e18aaaSAndroid Build Coastguard Worker    # Update test name if the test belong to extra config which means it's
257*c2e18aaaSAndroid Build Coastguard Worker    # test config name is not the same as module name. For extra config, it
258*c2e18aaaSAndroid Build Coastguard Worker    # index will be greater or equal to 1.
259*c2e18aaaSAndroid Build Coastguard Worker    try:
260*c2e18aaaSAndroid Build Coastguard Worker      if mod_info.get(constants.MODULE_TEST_CONFIG, []).index(rel_config) > 0:
261*c2e18aaaSAndroid Build Coastguard Worker        config_test_name = os.path.splitext(os.path.basename(rel_config))[0]
262*c2e18aaaSAndroid Build Coastguard Worker        logging.debug(
263*c2e18aaaSAndroid Build Coastguard Worker            'Replace test_info.name(%s) to %s', test.test_name, config_test_name
264*c2e18aaaSAndroid Build Coastguard Worker        )
265*c2e18aaaSAndroid Build Coastguard Worker        test.test_name = config_test_name
266*c2e18aaaSAndroid Build Coastguard Worker    except ValueError:
267*c2e18aaaSAndroid Build Coastguard Worker      pass
268*c2e18aaaSAndroid Build Coastguard Worker    return test
269*c2e18aaaSAndroid Build Coastguard Worker
270*c2e18aaaSAndroid Build Coastguard Worker  def _get_build_targets(self, module_name, rel_config):
271*c2e18aaaSAndroid Build Coastguard Worker    """Get the test deps.
272*c2e18aaaSAndroid Build Coastguard Worker
273*c2e18aaaSAndroid Build Coastguard Worker    Args:
274*c2e18aaaSAndroid Build Coastguard Worker        module_name: name of the test.
275*c2e18aaaSAndroid Build Coastguard Worker        rel_config: XML for the given test.
276*c2e18aaaSAndroid Build Coastguard Worker
277*c2e18aaaSAndroid Build Coastguard Worker    Returns:
278*c2e18aaaSAndroid Build Coastguard Worker        Set of build targets.
279*c2e18aaaSAndroid Build Coastguard Worker    """
280*c2e18aaaSAndroid Build Coastguard Worker    targets = set()
281*c2e18aaaSAndroid Build Coastguard Worker    if not self.module_info.is_auto_gen_test_config(module_name):
282*c2e18aaaSAndroid Build Coastguard Worker      config_file = os.path.join(self.root_dir, rel_config)
283*c2e18aaaSAndroid Build Coastguard Worker      targets = test_finder_utils.get_targets_from_xml(
284*c2e18aaaSAndroid Build Coastguard Worker          config_file, self.module_info
285*c2e18aaaSAndroid Build Coastguard Worker      )
286*c2e18aaaSAndroid Build Coastguard Worker    if constants.VTS_CORE_SUITE in self.module_info.get_module_info(
287*c2e18aaaSAndroid Build Coastguard Worker        module_name
288*c2e18aaaSAndroid Build Coastguard Worker    ).get(constants.MODULE_COMPATIBILITY_SUITES, []):
289*c2e18aaaSAndroid Build Coastguard Worker      targets.add(constants.VTS_CORE_TF_MODULE)
290*c2e18aaaSAndroid Build Coastguard Worker    for suite in self.module_info.get_module_info(module_name).get(
291*c2e18aaaSAndroid Build Coastguard Worker        constants.MODULE_COMPATIBILITY_SUITES, []
292*c2e18aaaSAndroid Build Coastguard Worker    ):
293*c2e18aaaSAndroid Build Coastguard Worker      targets.update(constants.SUITE_DEPS.get(suite, []))
294*c2e18aaaSAndroid Build Coastguard Worker    for module_path in self.module_info.get_paths(module_name):
295*c2e18aaaSAndroid Build Coastguard Worker      mod_dir = module_path.replace('/', '-')
296*c2e18aaaSAndroid Build Coastguard Worker      targets.add(constants.MODULES_IN + mod_dir)
297*c2e18aaaSAndroid Build Coastguard Worker    # (b/184567849) Force adding module_name as a build_target. This will
298*c2e18aaaSAndroid Build Coastguard Worker    # allow excluding MODULES-IN-* and prevent from missing build targets.
299*c2e18aaaSAndroid Build Coastguard Worker    if module_name and self.module_info.is_module(module_name):
300*c2e18aaaSAndroid Build Coastguard Worker      targets.add(module_name)
301*c2e18aaaSAndroid Build Coastguard Worker    # If it's a MTS test, add cts-tradefed as test dependency.
302*c2e18aaaSAndroid Build Coastguard Worker    if constants.MTS_SUITE in self.module_info.get_module_info(module_name).get(
303*c2e18aaaSAndroid Build Coastguard Worker        constants.MODULE_COMPATIBILITY_SUITES, []
304*c2e18aaaSAndroid Build Coastguard Worker    ):
305*c2e18aaaSAndroid Build Coastguard Worker      if self.module_info.is_module(constants.CTS_JAR):
306*c2e18aaaSAndroid Build Coastguard Worker        targets.add(constants.CTS_JAR)
307*c2e18aaaSAndroid Build Coastguard Worker    return targets
308*c2e18aaaSAndroid Build Coastguard Worker
309*c2e18aaaSAndroid Build Coastguard Worker  def _get_module_test_config(self, module_name, rel_config=None) -> list[str]:
310*c2e18aaaSAndroid Build Coastguard Worker    """Get the value of test_config in module_info.
311*c2e18aaaSAndroid Build Coastguard Worker
312*c2e18aaaSAndroid Build Coastguard Worker    Get the value of 'test_config' in module_info if its
313*c2e18aaaSAndroid Build Coastguard Worker    auto_test_config is not true.
314*c2e18aaaSAndroid Build Coastguard Worker    In this case, the test_config is specified by user.
315*c2e18aaaSAndroid Build Coastguard Worker    If not, return rel_config.
316*c2e18aaaSAndroid Build Coastguard Worker
317*c2e18aaaSAndroid Build Coastguard Worker    Args:
318*c2e18aaaSAndroid Build Coastguard Worker        module_name: A string of the test's module name.
319*c2e18aaaSAndroid Build Coastguard Worker        rel_config: XML for the given test.
320*c2e18aaaSAndroid Build Coastguard Worker
321*c2e18aaaSAndroid Build Coastguard Worker    Returns:
322*c2e18aaaSAndroid Build Coastguard Worker        A list of string of test_config path if found, else return rel_config.
323*c2e18aaaSAndroid Build Coastguard Worker    """
324*c2e18aaaSAndroid Build Coastguard Worker    default_all_config = not (
325*c2e18aaaSAndroid Build Coastguard Worker        atest_configs.GLOBAL_ARGS
326*c2e18aaaSAndroid Build Coastguard Worker        and atest_configs.GLOBAL_ARGS.test_config_select
327*c2e18aaaSAndroid Build Coastguard Worker    )
328*c2e18aaaSAndroid Build Coastguard Worker    mod_info = self.module_info.get_module_info(module_name)
329*c2e18aaaSAndroid Build Coastguard Worker    if mod_info:
330*c2e18aaaSAndroid Build Coastguard Worker      test_configs = []
331*c2e18aaaSAndroid Build Coastguard Worker      test_config_list = mod_info.get(constants.MODULE_TEST_CONFIG, [])
332*c2e18aaaSAndroid Build Coastguard Worker      if test_config_list:
333*c2e18aaaSAndroid Build Coastguard Worker        # multiple test configs
334*c2e18aaaSAndroid Build Coastguard Worker        if len(test_config_list) > 1:
335*c2e18aaaSAndroid Build Coastguard Worker          test_configs = test_finder_utils.extract_selected_tests(
336*c2e18aaaSAndroid Build Coastguard Worker              test_config_list, default_all=default_all_config
337*c2e18aaaSAndroid Build Coastguard Worker          )
338*c2e18aaaSAndroid Build Coastguard Worker        else:
339*c2e18aaaSAndroid Build Coastguard Worker          test_configs = test_config_list
340*c2e18aaaSAndroid Build Coastguard Worker      if test_configs:
341*c2e18aaaSAndroid Build Coastguard Worker        return test_configs
342*c2e18aaaSAndroid Build Coastguard Worker      # Double check if below section is needed.
343*c2e18aaaSAndroid Build Coastguard Worker      if (
344*c2e18aaaSAndroid Build Coastguard Worker          not self.module_info.is_auto_gen_test_config(module_name)
345*c2e18aaaSAndroid Build Coastguard Worker          and test_configs
346*c2e18aaaSAndroid Build Coastguard Worker      ):
347*c2e18aaaSAndroid Build Coastguard Worker        return test_configs
348*c2e18aaaSAndroid Build Coastguard Worker    return [rel_config] if rel_config else []
349*c2e18aaaSAndroid Build Coastguard Worker
350*c2e18aaaSAndroid Build Coastguard Worker  # pylint: disable=too-many-branches
351*c2e18aaaSAndroid Build Coastguard Worker  # pylint: disable=too-many-locals
352*c2e18aaaSAndroid Build Coastguard Worker  def _get_test_info_filter(
353*c2e18aaaSAndroid Build Coastguard Worker      self, path, methods, rel_module_dir=None, class_name=None,
354*c2e18aaaSAndroid Build Coastguard Worker      is_native_test=False
355*c2e18aaaSAndroid Build Coastguard Worker  ):
356*c2e18aaaSAndroid Build Coastguard Worker    """Get test info filter.
357*c2e18aaaSAndroid Build Coastguard Worker
358*c2e18aaaSAndroid Build Coastguard Worker    Args:
359*c2e18aaaSAndroid Build Coastguard Worker        path: A string of the test's path.
360*c2e18aaaSAndroid Build Coastguard Worker        methods: A set of method name strings.
361*c2e18aaaSAndroid Build Coastguard Worker        rel_module_dir: Optional. A string of the module dir no-absolute to
362*c2e18aaaSAndroid Build Coastguard Worker          root.
363*c2e18aaaSAndroid Build Coastguard Worker        class_name: Optional. A string of the class name.
364*c2e18aaaSAndroid Build Coastguard Worker        is_native_test: Optional. A boolean variable of whether to search for
365*c2e18aaaSAndroid Build Coastguard Worker          a native test or not.
366*c2e18aaaSAndroid Build Coastguard Worker
367*c2e18aaaSAndroid Build Coastguard Worker    Returns:
368*c2e18aaaSAndroid Build Coastguard Worker        A set of test info filter.
369*c2e18aaaSAndroid Build Coastguard Worker    """
370*c2e18aaaSAndroid Build Coastguard Worker    _, file_name = test_finder_utils.get_dir_path_and_filename(path)
371*c2e18aaaSAndroid Build Coastguard Worker    ti_filter = frozenset()
372*c2e18aaaSAndroid Build Coastguard Worker    if os.path.isfile(path) and is_native_test:
373*c2e18aaaSAndroid Build Coastguard Worker      class_info = test_finder_utils.get_cc_class_info(path)
374*c2e18aaaSAndroid Build Coastguard Worker      ti_filter = frozenset([
375*c2e18aaaSAndroid Build Coastguard Worker          test_info.TestFilter(
376*c2e18aaaSAndroid Build Coastguard Worker              test_filter_utils.get_cc_filter(
377*c2e18aaaSAndroid Build Coastguard Worker                  class_info,
378*c2e18aaaSAndroid Build Coastguard Worker                  class_name if class_name is not None else '*', methods
379*c2e18aaaSAndroid Build Coastguard Worker              ),
380*c2e18aaaSAndroid Build Coastguard Worker              frozenset(),
381*c2e18aaaSAndroid Build Coastguard Worker          )
382*c2e18aaaSAndroid Build Coastguard Worker      ])
383*c2e18aaaSAndroid Build Coastguard Worker    # Path to java file.
384*c2e18aaaSAndroid Build Coastguard Worker    elif file_name and constants.JAVA_EXT_RE.match(file_name):
385*c2e18aaaSAndroid Build Coastguard Worker      full_class_name = test_filter_utils.get_fully_qualified_class_name(path)
386*c2e18aaaSAndroid Build Coastguard Worker      methods = frozenset(
387*c2e18aaaSAndroid Build Coastguard Worker          test_filter_utils.get_java_method_filters(path, methods)
388*c2e18aaaSAndroid Build Coastguard Worker      )
389*c2e18aaaSAndroid Build Coastguard Worker      ti_filter = frozenset([test_info.TestFilter(full_class_name, methods)])
390*c2e18aaaSAndroid Build Coastguard Worker    # Path to cc file.
391*c2e18aaaSAndroid Build Coastguard Worker    elif file_name and constants.CC_EXT_RE.match(file_name):
392*c2e18aaaSAndroid Build Coastguard Worker      # TODO: b/173019813 - Should setup correct filter for an input file.
393*c2e18aaaSAndroid Build Coastguard Worker      if not test_finder_utils.has_cc_class(path):
394*c2e18aaaSAndroid Build Coastguard Worker        raise atest_error.MissingCCTestCaseError(
395*c2e18aaaSAndroid Build Coastguard Worker            "Can't find CC class in %s" % path
396*c2e18aaaSAndroid Build Coastguard Worker        )
397*c2e18aaaSAndroid Build Coastguard Worker      class_info = test_finder_utils.get_cc_class_info(path)
398*c2e18aaaSAndroid Build Coastguard Worker      cc_filters = []
399*c2e18aaaSAndroid Build Coastguard Worker      for classname, _ in class_info.items():
400*c2e18aaaSAndroid Build Coastguard Worker        cc_filters.append(
401*c2e18aaaSAndroid Build Coastguard Worker            test_info.TestFilter(
402*c2e18aaaSAndroid Build Coastguard Worker                test_filter_utils.get_cc_filter(class_info, classname, methods),
403*c2e18aaaSAndroid Build Coastguard Worker                frozenset(),
404*c2e18aaaSAndroid Build Coastguard Worker            )
405*c2e18aaaSAndroid Build Coastguard Worker        )
406*c2e18aaaSAndroid Build Coastguard Worker      ti_filter = frozenset(cc_filters)
407*c2e18aaaSAndroid Build Coastguard Worker    # If input path is a folder and have class_name information.
408*c2e18aaaSAndroid Build Coastguard Worker    elif not file_name and class_name:
409*c2e18aaaSAndroid Build Coastguard Worker      ti_filter = frozenset(
410*c2e18aaaSAndroid Build Coastguard Worker          [test_info.TestFilter(class_name, methods)]
411*c2e18aaaSAndroid Build Coastguard Worker      )
412*c2e18aaaSAndroid Build Coastguard Worker    # Path to non-module dir, treat as package.
413*c2e18aaaSAndroid Build Coastguard Worker    elif not file_name and rel_module_dir != os.path.relpath(
414*c2e18aaaSAndroid Build Coastguard Worker        path, self.root_dir):
415*c2e18aaaSAndroid Build Coastguard Worker      dir_items = [os.path.join(path, f) for f in os.listdir(path)]
416*c2e18aaaSAndroid Build Coastguard Worker      for dir_item in dir_items:
417*c2e18aaaSAndroid Build Coastguard Worker        if constants.JAVA_EXT_RE.match(dir_item):
418*c2e18aaaSAndroid Build Coastguard Worker          package_name = test_filter_utils.get_package_name(dir_item)
419*c2e18aaaSAndroid Build Coastguard Worker          if package_name:
420*c2e18aaaSAndroid Build Coastguard Worker            # methods should be empty frozenset for package.
421*c2e18aaaSAndroid Build Coastguard Worker            if methods:
422*c2e18aaaSAndroid Build Coastguard Worker              raise atest_error.MethodWithoutClassError(
423*c2e18aaaSAndroid Build Coastguard Worker                  '%s: Method filtering requires class' % str(methods)
424*c2e18aaaSAndroid Build Coastguard Worker              )
425*c2e18aaaSAndroid Build Coastguard Worker            ti_filter = frozenset([test_info.TestFilter(package_name, methods)])
426*c2e18aaaSAndroid Build Coastguard Worker            break
427*c2e18aaaSAndroid Build Coastguard Worker    logging.debug('_get_test_info_filter() ti_filter: %s', ti_filter)
428*c2e18aaaSAndroid Build Coastguard Worker    return ti_filter
429*c2e18aaaSAndroid Build Coastguard Worker
430*c2e18aaaSAndroid Build Coastguard Worker  def _get_rel_config(self, test_path):
431*c2e18aaaSAndroid Build Coastguard Worker    """Get config file's no-absolute path.
432*c2e18aaaSAndroid Build Coastguard Worker
433*c2e18aaaSAndroid Build Coastguard Worker    Args:
434*c2e18aaaSAndroid Build Coastguard Worker        test_path: A string of the test absolute path.
435*c2e18aaaSAndroid Build Coastguard Worker
436*c2e18aaaSAndroid Build Coastguard Worker    Returns:
437*c2e18aaaSAndroid Build Coastguard Worker        A string of config's no-absolute path, else None.
438*c2e18aaaSAndroid Build Coastguard Worker    """
439*c2e18aaaSAndroid Build Coastguard Worker    test_dir = os.path.dirname(test_path)
440*c2e18aaaSAndroid Build Coastguard Worker    rel_module_dir = test_finder_utils.find_parent_module_dir(
441*c2e18aaaSAndroid Build Coastguard Worker        self.root_dir, test_dir, self.module_info
442*c2e18aaaSAndroid Build Coastguard Worker    )
443*c2e18aaaSAndroid Build Coastguard Worker    if rel_module_dir:
444*c2e18aaaSAndroid Build Coastguard Worker      return os.path.join(rel_module_dir, constants.MODULE_CONFIG)
445*c2e18aaaSAndroid Build Coastguard Worker    return None
446*c2e18aaaSAndroid Build Coastguard Worker
447*c2e18aaaSAndroid Build Coastguard Worker  def _get_test_infos(self, test_path, rel_config, module_name, test_filter):
448*c2e18aaaSAndroid Build Coastguard Worker    """Get test_info for test_path.
449*c2e18aaaSAndroid Build Coastguard Worker
450*c2e18aaaSAndroid Build Coastguard Worker    Args:
451*c2e18aaaSAndroid Build Coastguard Worker        test_path: A string of the test path.
452*c2e18aaaSAndroid Build Coastguard Worker        rel_config: A string of rel path of config.
453*c2e18aaaSAndroid Build Coastguard Worker        module_name: A string of the module name to use.
454*c2e18aaaSAndroid Build Coastguard Worker        test_filter: A test info filter.
455*c2e18aaaSAndroid Build Coastguard Worker
456*c2e18aaaSAndroid Build Coastguard Worker    Returns:
457*c2e18aaaSAndroid Build Coastguard Worker        A list of TestInfo namedtuple if found, else None.
458*c2e18aaaSAndroid Build Coastguard Worker    """
459*c2e18aaaSAndroid Build Coastguard Worker    if not rel_config:
460*c2e18aaaSAndroid Build Coastguard Worker      rel_config = self._get_rel_config(test_path)
461*c2e18aaaSAndroid Build Coastguard Worker      if not rel_config:
462*c2e18aaaSAndroid Build Coastguard Worker        return None
463*c2e18aaaSAndroid Build Coastguard Worker    if module_name:
464*c2e18aaaSAndroid Build Coastguard Worker      module_names = [module_name]
465*c2e18aaaSAndroid Build Coastguard Worker    else:
466*c2e18aaaSAndroid Build Coastguard Worker      module_names = self._determine_modules_to_test(
467*c2e18aaaSAndroid Build Coastguard Worker          os.path.dirname(rel_config),
468*c2e18aaaSAndroid Build Coastguard Worker          test_path if self._is_comparted_src(test_path) else None,
469*c2e18aaaSAndroid Build Coastguard Worker      )
470*c2e18aaaSAndroid Build Coastguard Worker    test_infos = []
471*c2e18aaaSAndroid Build Coastguard Worker    if module_names:
472*c2e18aaaSAndroid Build Coastguard Worker      for mname in module_names:
473*c2e18aaaSAndroid Build Coastguard Worker        # The real test config might be record in module-info.
474*c2e18aaaSAndroid Build Coastguard Worker        mod_info = self.module_info.get_module_info(mname)
475*c2e18aaaSAndroid Build Coastguard Worker        if not mod_info:
476*c2e18aaaSAndroid Build Coastguard Worker          continue
477*c2e18aaaSAndroid Build Coastguard Worker        rel_configs = self._get_module_test_config(mname, rel_config=rel_config)
478*c2e18aaaSAndroid Build Coastguard Worker        for rel_cfg in rel_configs:
479*c2e18aaaSAndroid Build Coastguard Worker          tinfo = self._process_test_info(
480*c2e18aaaSAndroid Build Coastguard Worker              test_info.TestInfo(
481*c2e18aaaSAndroid Build Coastguard Worker                  test_name=mname,
482*c2e18aaaSAndroid Build Coastguard Worker                  test_runner=self._TEST_RUNNER,
483*c2e18aaaSAndroid Build Coastguard Worker                  build_targets=set(),
484*c2e18aaaSAndroid Build Coastguard Worker                  data={
485*c2e18aaaSAndroid Build Coastguard Worker                      constants.TI_FILTER: test_filter,
486*c2e18aaaSAndroid Build Coastguard Worker                      constants.TI_REL_CONFIG: rel_cfg,
487*c2e18aaaSAndroid Build Coastguard Worker                  },
488*c2e18aaaSAndroid Build Coastguard Worker                  compatibility_suites=mod_info.get(
489*c2e18aaaSAndroid Build Coastguard Worker                      constants.MODULE_COMPATIBILITY_SUITES, []
490*c2e18aaaSAndroid Build Coastguard Worker                  ),
491*c2e18aaaSAndroid Build Coastguard Worker              )
492*c2e18aaaSAndroid Build Coastguard Worker          )
493*c2e18aaaSAndroid Build Coastguard Worker          if tinfo:
494*c2e18aaaSAndroid Build Coastguard Worker            test_infos.append(tinfo)
495*c2e18aaaSAndroid Build Coastguard Worker    return test_infos
496*c2e18aaaSAndroid Build Coastguard Worker
497*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_module_name(self, module_name):
498*c2e18aaaSAndroid Build Coastguard Worker    """Find test for the given module name.
499*c2e18aaaSAndroid Build Coastguard Worker
500*c2e18aaaSAndroid Build Coastguard Worker    Args:
501*c2e18aaaSAndroid Build Coastguard Worker        module_name: A string of the test's module name.
502*c2e18aaaSAndroid Build Coastguard Worker
503*c2e18aaaSAndroid Build Coastguard Worker    Returns:
504*c2e18aaaSAndroid Build Coastguard Worker        A list that includes only 1 populated TestInfo namedtuple
505*c2e18aaaSAndroid Build Coastguard Worker        if found, otherwise None.
506*c2e18aaaSAndroid Build Coastguard Worker    """
507*c2e18aaaSAndroid Build Coastguard Worker    tinfos = []
508*c2e18aaaSAndroid Build Coastguard Worker    mod_info = self.module_info.get_module_info(module_name)
509*c2e18aaaSAndroid Build Coastguard Worker    if self.module_info.is_testable_module(mod_info):
510*c2e18aaaSAndroid Build Coastguard Worker      # path is a list with only 1 element.
511*c2e18aaaSAndroid Build Coastguard Worker      rel_config = os.path.join(
512*c2e18aaaSAndroid Build Coastguard Worker          mod_info[constants.MODULE_PATH][0], constants.MODULE_CONFIG
513*c2e18aaaSAndroid Build Coastguard Worker      )
514*c2e18aaaSAndroid Build Coastguard Worker      rel_configs = self._get_module_test_config(
515*c2e18aaaSAndroid Build Coastguard Worker          module_name, rel_config=rel_config
516*c2e18aaaSAndroid Build Coastguard Worker      )
517*c2e18aaaSAndroid Build Coastguard Worker      for rel_config in rel_configs:
518*c2e18aaaSAndroid Build Coastguard Worker        tinfo = self._process_test_info(
519*c2e18aaaSAndroid Build Coastguard Worker            test_info.TestInfo(
520*c2e18aaaSAndroid Build Coastguard Worker                test_name=module_name,
521*c2e18aaaSAndroid Build Coastguard Worker                test_runner=self._TEST_RUNNER,
522*c2e18aaaSAndroid Build Coastguard Worker                build_targets=set(),
523*c2e18aaaSAndroid Build Coastguard Worker                data={
524*c2e18aaaSAndroid Build Coastguard Worker                    constants.TI_REL_CONFIG: rel_config,
525*c2e18aaaSAndroid Build Coastguard Worker                    constants.TI_FILTER: frozenset(),
526*c2e18aaaSAndroid Build Coastguard Worker                },
527*c2e18aaaSAndroid Build Coastguard Worker                compatibility_suites=mod_info.get(
528*c2e18aaaSAndroid Build Coastguard Worker                    constants.MODULE_COMPATIBILITY_SUITES, []
529*c2e18aaaSAndroid Build Coastguard Worker                ),
530*c2e18aaaSAndroid Build Coastguard Worker            )
531*c2e18aaaSAndroid Build Coastguard Worker        )
532*c2e18aaaSAndroid Build Coastguard Worker        if tinfo:
533*c2e18aaaSAndroid Build Coastguard Worker          tinfos.append(tinfo)
534*c2e18aaaSAndroid Build Coastguard Worker      if tinfos:
535*c2e18aaaSAndroid Build Coastguard Worker        return tinfos
536*c2e18aaaSAndroid Build Coastguard Worker    return None
537*c2e18aaaSAndroid Build Coastguard Worker
538*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_kernel_class_name(self, module_name, class_name):
539*c2e18aaaSAndroid Build Coastguard Worker    """Find kernel test for the given class name.
540*c2e18aaaSAndroid Build Coastguard Worker
541*c2e18aaaSAndroid Build Coastguard Worker    Args:
542*c2e18aaaSAndroid Build Coastguard Worker        module_name: A string of the module name to use.
543*c2e18aaaSAndroid Build Coastguard Worker        class_name: A string of the test's class name.
544*c2e18aaaSAndroid Build Coastguard Worker
545*c2e18aaaSAndroid Build Coastguard Worker    Returns:
546*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if test found, else None.
547*c2e18aaaSAndroid Build Coastguard Worker    """
548*c2e18aaaSAndroid Build Coastguard Worker
549*c2e18aaaSAndroid Build Coastguard Worker    class_name, methods = test_filter_utils.split_methods(class_name)
550*c2e18aaaSAndroid Build Coastguard Worker    test_configs = self._get_module_test_config(module_name)
551*c2e18aaaSAndroid Build Coastguard Worker    if not test_configs:
552*c2e18aaaSAndroid Build Coastguard Worker      return None
553*c2e18aaaSAndroid Build Coastguard Worker    tinfos = []
554*c2e18aaaSAndroid Build Coastguard Worker    for test_config in test_configs:
555*c2e18aaaSAndroid Build Coastguard Worker      test_config_path = os.path.join(self.root_dir, test_config)
556*c2e18aaaSAndroid Build Coastguard Worker      mod_info = self.module_info.get_module_info(module_name)
557*c2e18aaaSAndroid Build Coastguard Worker      ti_filter = frozenset([test_info.TestFilter(class_name, methods)])
558*c2e18aaaSAndroid Build Coastguard Worker      if test_finder_utils.is_test_from_kernel_xml(
559*c2e18aaaSAndroid Build Coastguard Worker          test_config_path, class_name
560*c2e18aaaSAndroid Build Coastguard Worker      ):
561*c2e18aaaSAndroid Build Coastguard Worker        tinfo = self._process_test_info(
562*c2e18aaaSAndroid Build Coastguard Worker            test_info.TestInfo(
563*c2e18aaaSAndroid Build Coastguard Worker                test_name=module_name,
564*c2e18aaaSAndroid Build Coastguard Worker                test_runner=self._TEST_RUNNER,
565*c2e18aaaSAndroid Build Coastguard Worker                build_targets=set(),
566*c2e18aaaSAndroid Build Coastguard Worker                data={
567*c2e18aaaSAndroid Build Coastguard Worker                    constants.TI_REL_CONFIG: test_config,
568*c2e18aaaSAndroid Build Coastguard Worker                    constants.TI_FILTER: ti_filter,
569*c2e18aaaSAndroid Build Coastguard Worker                },
570*c2e18aaaSAndroid Build Coastguard Worker                compatibility_suites=mod_info.get(
571*c2e18aaaSAndroid Build Coastguard Worker                    constants.MODULE_COMPATIBILITY_SUITES, []
572*c2e18aaaSAndroid Build Coastguard Worker                ),
573*c2e18aaaSAndroid Build Coastguard Worker            )
574*c2e18aaaSAndroid Build Coastguard Worker        )
575*c2e18aaaSAndroid Build Coastguard Worker        if tinfo:
576*c2e18aaaSAndroid Build Coastguard Worker          tinfos.append(tinfo)
577*c2e18aaaSAndroid Build Coastguard Worker    if tinfos:
578*c2e18aaaSAndroid Build Coastguard Worker      return tinfos
579*c2e18aaaSAndroid Build Coastguard Worker    return None
580*c2e18aaaSAndroid Build Coastguard Worker
581*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_class_name(
582*c2e18aaaSAndroid Build Coastguard Worker      self,
583*c2e18aaaSAndroid Build Coastguard Worker      class_name: str,
584*c2e18aaaSAndroid Build Coastguard Worker      module_name: str = None,
585*c2e18aaaSAndroid Build Coastguard Worker      rel_config_path: str = None,
586*c2e18aaaSAndroid Build Coastguard Worker      is_native_test: bool = False,
587*c2e18aaaSAndroid Build Coastguard Worker  ) -> list[test_info.TestInfo] | None:
588*c2e18aaaSAndroid Build Coastguard Worker    """Find test files given a class name.
589*c2e18aaaSAndroid Build Coastguard Worker
590*c2e18aaaSAndroid Build Coastguard Worker    If module_name and rel_config not given it will calculate it determine
591*c2e18aaaSAndroid Build Coastguard Worker    it by looking up the tree from the class file.
592*c2e18aaaSAndroid Build Coastguard Worker
593*c2e18aaaSAndroid Build Coastguard Worker    Args:
594*c2e18aaaSAndroid Build Coastguard Worker        class_name: A string of the test's class name.
595*c2e18aaaSAndroid Build Coastguard Worker        module_name: Optional. A string of the module name to use.
596*c2e18aaaSAndroid Build Coastguard Worker        rel_config_path: Optional. A string of module dir relative to repo root.
597*c2e18aaaSAndroid Build Coastguard Worker        is_native_test: A boolean variable of whether to search for a native
598*c2e18aaaSAndroid Build Coastguard Worker          test or not.
599*c2e18aaaSAndroid Build Coastguard Worker
600*c2e18aaaSAndroid Build Coastguard Worker    Returns:
601*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if test found, else None.
602*c2e18aaaSAndroid Build Coastguard Worker    """
603*c2e18aaaSAndroid Build Coastguard Worker    class_name, methods = test_filter_utils.split_methods(class_name)
604*c2e18aaaSAndroid Build Coastguard Worker    search_class_name = class_name
605*c2e18aaaSAndroid Build Coastguard Worker    # For parameterized gtest, test class will be automerged to
606*c2e18aaaSAndroid Build Coastguard Worker    # $(class_prefix)/$(base_class) name. Using $(base_class) for searching
607*c2e18aaaSAndroid Build Coastguard Worker    # matched TEST_P to make sure test class is matched.
608*c2e18aaaSAndroid Build Coastguard Worker    if '/' in search_class_name:
609*c2e18aaaSAndroid Build Coastguard Worker      search_class_name = str(search_class_name).split('/')[-1]
610*c2e18aaaSAndroid Build Coastguard Worker
611*c2e18aaaSAndroid Build Coastguard Worker    test_paths = []
612*c2e18aaaSAndroid Build Coastguard Worker    # Search using the path where the config file is located.
613*c2e18aaaSAndroid Build Coastguard Worker    if rel_config_path:
614*c2e18aaaSAndroid Build Coastguard Worker      test_paths = test_finder_utils.find_class_file(
615*c2e18aaaSAndroid Build Coastguard Worker          os.path.join(self.root_dir, os.path.dirname(rel_config_path)),
616*c2e18aaaSAndroid Build Coastguard Worker          search_class_name,
617*c2e18aaaSAndroid Build Coastguard Worker          is_native_test,
618*c2e18aaaSAndroid Build Coastguard Worker          methods,
619*c2e18aaaSAndroid Build Coastguard Worker      )
620*c2e18aaaSAndroid Build Coastguard Worker      if not test_paths:
621*c2e18aaaSAndroid Build Coastguard Worker        atest_utils.print_and_log_info(
622*c2e18aaaSAndroid Build Coastguard Worker            'Did not find class (%s) under module path (%s), '
623*c2e18aaaSAndroid Build Coastguard Worker            'researching from repo root.',
624*c2e18aaaSAndroid Build Coastguard Worker            class_name,
625*c2e18aaaSAndroid Build Coastguard Worker            rel_config_path,
626*c2e18aaaSAndroid Build Coastguard Worker        )
627*c2e18aaaSAndroid Build Coastguard Worker    # Search from the root dir.
628*c2e18aaaSAndroid Build Coastguard Worker    if not test_paths:
629*c2e18aaaSAndroid Build Coastguard Worker      test_paths = test_finder_utils.find_class_file(
630*c2e18aaaSAndroid Build Coastguard Worker          self.root_dir, search_class_name, is_native_test, methods
631*c2e18aaaSAndroid Build Coastguard Worker      )
632*c2e18aaaSAndroid Build Coastguard Worker    # If we already have module name, use path in module-info as test_path.
633*c2e18aaaSAndroid Build Coastguard Worker    if not test_paths:
634*c2e18aaaSAndroid Build Coastguard Worker      if not module_name:
635*c2e18aaaSAndroid Build Coastguard Worker        return None
636*c2e18aaaSAndroid Build Coastguard Worker      # Use the module path as test_path.
637*c2e18aaaSAndroid Build Coastguard Worker      module_paths = self.module_info.get_paths(module_name)
638*c2e18aaaSAndroid Build Coastguard Worker      test_paths = []
639*c2e18aaaSAndroid Build Coastguard Worker      for rel_module_path in module_paths:
640*c2e18aaaSAndroid Build Coastguard Worker        test_paths.append(os.path.join(self.root_dir, rel_module_path))
641*c2e18aaaSAndroid Build Coastguard Worker
642*c2e18aaaSAndroid Build Coastguard Worker    tinfos = []
643*c2e18aaaSAndroid Build Coastguard Worker    for test_path in test_paths:
644*c2e18aaaSAndroid Build Coastguard Worker      test_filter = self._get_test_info_filter(
645*c2e18aaaSAndroid Build Coastguard Worker          test_path,
646*c2e18aaaSAndroid Build Coastguard Worker          methods,
647*c2e18aaaSAndroid Build Coastguard Worker          class_name=class_name,
648*c2e18aaaSAndroid Build Coastguard Worker          is_native_test=is_native_test,
649*c2e18aaaSAndroid Build Coastguard Worker      )
650*c2e18aaaSAndroid Build Coastguard Worker      test_infos = self._get_test_infos(
651*c2e18aaaSAndroid Build Coastguard Worker          test_path, rel_config_path, module_name, test_filter
652*c2e18aaaSAndroid Build Coastguard Worker      )
653*c2e18aaaSAndroid Build Coastguard Worker      # If input include methods, check if tinfo match.
654*c2e18aaaSAndroid Build Coastguard Worker      if test_infos and len(test_infos) > 1 and methods:
655*c2e18aaaSAndroid Build Coastguard Worker        test_infos = self._get_matched_test_infos(test_infos, methods)
656*c2e18aaaSAndroid Build Coastguard Worker      if test_infos:
657*c2e18aaaSAndroid Build Coastguard Worker        tinfos.extend(test_infos)
658*c2e18aaaSAndroid Build Coastguard Worker
659*c2e18aaaSAndroid Build Coastguard Worker    return tinfos if tinfos else None
660*c2e18aaaSAndroid Build Coastguard Worker
661*c2e18aaaSAndroid Build Coastguard Worker  def _get_matched_test_infos(self, test_infos, methods):
662*c2e18aaaSAndroid Build Coastguard Worker    """Get the test_infos matched the given methods.
663*c2e18aaaSAndroid Build Coastguard Worker
664*c2e18aaaSAndroid Build Coastguard Worker    Args:
665*c2e18aaaSAndroid Build Coastguard Worker        test_infos: A list of TestInfo obj.
666*c2e18aaaSAndroid Build Coastguard Worker        methods: A set of method name strings.
667*c2e18aaaSAndroid Build Coastguard Worker
668*c2e18aaaSAndroid Build Coastguard Worker    Returns:
669*c2e18aaaSAndroid Build Coastguard Worker        A list of matched TestInfo namedtuple, else None.
670*c2e18aaaSAndroid Build Coastguard Worker    """
671*c2e18aaaSAndroid Build Coastguard Worker    matched_test_infos = set()
672*c2e18aaaSAndroid Build Coastguard Worker    for tinfo in test_infos:
673*c2e18aaaSAndroid Build Coastguard Worker      test_config, test_srcs = test_finder_utils.get_test_config_and_srcs(
674*c2e18aaaSAndroid Build Coastguard Worker          tinfo, self.module_info
675*c2e18aaaSAndroid Build Coastguard Worker      )
676*c2e18aaaSAndroid Build Coastguard Worker      if test_config:
677*c2e18aaaSAndroid Build Coastguard Worker        filter_dict = atest_utils.get_android_junit_config_filters(test_config)
678*c2e18aaaSAndroid Build Coastguard Worker        # Always treat the test_info is matched if no filters found.
679*c2e18aaaSAndroid Build Coastguard Worker        if not filter_dict.keys():
680*c2e18aaaSAndroid Build Coastguard Worker          matched_test_infos.add(tinfo)
681*c2e18aaaSAndroid Build Coastguard Worker          continue
682*c2e18aaaSAndroid Build Coastguard Worker        for method in methods:
683*c2e18aaaSAndroid Build Coastguard Worker          if self._is_srcs_match_method_annotation(
684*c2e18aaaSAndroid Build Coastguard Worker              method, test_srcs, filter_dict
685*c2e18aaaSAndroid Build Coastguard Worker          ):
686*c2e18aaaSAndroid Build Coastguard Worker            logging.debug(
687*c2e18aaaSAndroid Build Coastguard Worker                'For method:%s Test:%s matched filter_dict: %s',
688*c2e18aaaSAndroid Build Coastguard Worker                method,
689*c2e18aaaSAndroid Build Coastguard Worker                tinfo.test_name,
690*c2e18aaaSAndroid Build Coastguard Worker                filter_dict,
691*c2e18aaaSAndroid Build Coastguard Worker            )
692*c2e18aaaSAndroid Build Coastguard Worker            matched_test_infos.add(tinfo)
693*c2e18aaaSAndroid Build Coastguard Worker    return list(matched_test_infos)
694*c2e18aaaSAndroid Build Coastguard Worker
695*c2e18aaaSAndroid Build Coastguard Worker  def _is_srcs_match_method_annotation(self, method, srcs, annotation_dict):
696*c2e18aaaSAndroid Build Coastguard Worker    """Check if input srcs matched annotation.
697*c2e18aaaSAndroid Build Coastguard Worker
698*c2e18aaaSAndroid Build Coastguard Worker    Args:
699*c2e18aaaSAndroid Build Coastguard Worker        method: A string of test method name.
700*c2e18aaaSAndroid Build Coastguard Worker        srcs: A list of source file of test.
701*c2e18aaaSAndroid Build Coastguard Worker        annotation_dict: A dictionary record the include and exclude
702*c2e18aaaSAndroid Build Coastguard Worker          annotations.
703*c2e18aaaSAndroid Build Coastguard Worker
704*c2e18aaaSAndroid Build Coastguard Worker    Returns:
705*c2e18aaaSAndroid Build Coastguard Worker        True if input method matched the annotation of input srcs, else
706*c2e18aaaSAndroid Build Coastguard Worker        None.
707*c2e18aaaSAndroid Build Coastguard Worker    """
708*c2e18aaaSAndroid Build Coastguard Worker    include_annotations = annotation_dict.get(constants.INCLUDE_ANNOTATION, [])
709*c2e18aaaSAndroid Build Coastguard Worker    exclude_annotations = annotation_dict.get(constants.EXCLUDE_ANNOTATION, [])
710*c2e18aaaSAndroid Build Coastguard Worker    for src in srcs:
711*c2e18aaaSAndroid Build Coastguard Worker      include_methods = set()
712*c2e18aaaSAndroid Build Coastguard Worker      src_path = os.path.join(self.root_dir, src)
713*c2e18aaaSAndroid Build Coastguard Worker      # Add methods matched include_annotations.
714*c2e18aaaSAndroid Build Coastguard Worker      for annotation in include_annotations:
715*c2e18aaaSAndroid Build Coastguard Worker        include_methods.update(
716*c2e18aaaSAndroid Build Coastguard Worker            test_finder_utils.get_annotated_methods(annotation, src_path)
717*c2e18aaaSAndroid Build Coastguard Worker        )
718*c2e18aaaSAndroid Build Coastguard Worker      if exclude_annotations:
719*c2e18aaaSAndroid Build Coastguard Worker        # For exclude annotation, get all the method in the input srcs,
720*c2e18aaaSAndroid Build Coastguard Worker        # and filter out the matched annotation.
721*c2e18aaaSAndroid Build Coastguard Worker        exclude_methods = set()
722*c2e18aaaSAndroid Build Coastguard Worker        all_methods = test_finder_utils.get_java_methods(src_path)
723*c2e18aaaSAndroid Build Coastguard Worker        for annotation in exclude_annotations:
724*c2e18aaaSAndroid Build Coastguard Worker          exclude_methods.update(
725*c2e18aaaSAndroid Build Coastguard Worker              test_finder_utils.get_annotated_methods(annotation, src_path)
726*c2e18aaaSAndroid Build Coastguard Worker          )
727*c2e18aaaSAndroid Build Coastguard Worker        include_methods = all_methods - exclude_methods
728*c2e18aaaSAndroid Build Coastguard Worker      if method in include_methods:
729*c2e18aaaSAndroid Build Coastguard Worker        return True
730*c2e18aaaSAndroid Build Coastguard Worker    return False
731*c2e18aaaSAndroid Build Coastguard Worker
732*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_module_and_class(
733*c2e18aaaSAndroid Build Coastguard Worker      self, module_class: str
734*c2e18aaaSAndroid Build Coastguard Worker  ) -> list[test_info.TestInfo]:
735*c2e18aaaSAndroid Build Coastguard Worker    """Find the test info given a MODULE:CLASS string.
736*c2e18aaaSAndroid Build Coastguard Worker
737*c2e18aaaSAndroid Build Coastguard Worker    Args:
738*c2e18aaaSAndroid Build Coastguard Worker        module_class: A string of form MODULE:CLASS or MODULE:CLASS#METHOD.
739*c2e18aaaSAndroid Build Coastguard Worker
740*c2e18aaaSAndroid Build Coastguard Worker    Returns:
741*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo if found, else None.
742*c2e18aaaSAndroid Build Coastguard Worker    """
743*c2e18aaaSAndroid Build Coastguard Worker    parse_result = test_finder_utils.parse_test_reference(module_class)
744*c2e18aaaSAndroid Build Coastguard Worker    if not parse_result:
745*c2e18aaaSAndroid Build Coastguard Worker      return None
746*c2e18aaaSAndroid Build Coastguard Worker    module_name = parse_result['module_name']
747*c2e18aaaSAndroid Build Coastguard Worker    class_name = parse_result['pkg_class_name']
748*c2e18aaaSAndroid Build Coastguard Worker    method_name = parse_result.get('method_name', '')
749*c2e18aaaSAndroid Build Coastguard Worker    if method_name:
750*c2e18aaaSAndroid Build Coastguard Worker      class_name = class_name + '#' + method_name
751*c2e18aaaSAndroid Build Coastguard Worker
752*c2e18aaaSAndroid Build Coastguard Worker    # module_infos is a list of TestInfo with at most 1 element.
753*c2e18aaaSAndroid Build Coastguard Worker    module_infos = self.find_test_by_module_name(module_name)
754*c2e18aaaSAndroid Build Coastguard Worker    module_info = module_infos[0] if module_infos else None
755*c2e18aaaSAndroid Build Coastguard Worker    if not module_info:
756*c2e18aaaSAndroid Build Coastguard Worker      return None
757*c2e18aaaSAndroid Build Coastguard Worker    find_result = None
758*c2e18aaaSAndroid Build Coastguard Worker    # If the target module is JAVA or Python test, search class name.
759*c2e18aaaSAndroid Build Coastguard Worker    find_result = self.find_test_by_class_name(
760*c2e18aaaSAndroid Build Coastguard Worker        class_name,
761*c2e18aaaSAndroid Build Coastguard Worker        module_name,
762*c2e18aaaSAndroid Build Coastguard Worker        module_info.data.get(constants.TI_REL_CONFIG),
763*c2e18aaaSAndroid Build Coastguard Worker        self.module_info.is_native_test(module_name),
764*c2e18aaaSAndroid Build Coastguard Worker    )
765*c2e18aaaSAndroid Build Coastguard Worker    # kernel target test is also define as NATIVE_TEST in build system.
766*c2e18aaaSAndroid Build Coastguard Worker    # TODO: b/157210083 - Update find_test_by_kernel_class_name method to
767*c2e18aaaSAndroid Build Coastguard Worker    # support gen_rule use case.
768*c2e18aaaSAndroid Build Coastguard Worker    if not find_result:
769*c2e18aaaSAndroid Build Coastguard Worker      find_result = self.find_test_by_kernel_class_name(module_name, class_name)
770*c2e18aaaSAndroid Build Coastguard Worker    # Find by cc class.
771*c2e18aaaSAndroid Build Coastguard Worker    if not find_result:
772*c2e18aaaSAndroid Build Coastguard Worker      find_result = self.find_test_by_cc_class_name(
773*c2e18aaaSAndroid Build Coastguard Worker          class_name,
774*c2e18aaaSAndroid Build Coastguard Worker          module_info.test_name,
775*c2e18aaaSAndroid Build Coastguard Worker          module_info.data.get(constants.TI_REL_CONFIG),
776*c2e18aaaSAndroid Build Coastguard Worker      )
777*c2e18aaaSAndroid Build Coastguard Worker    return find_result
778*c2e18aaaSAndroid Build Coastguard Worker
779*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_package_name(
780*c2e18aaaSAndroid Build Coastguard Worker      self, package, module_name=None, rel_config=None
781*c2e18aaaSAndroid Build Coastguard Worker  ):
782*c2e18aaaSAndroid Build Coastguard Worker    """Find the test info given a PACKAGE string.
783*c2e18aaaSAndroid Build Coastguard Worker
784*c2e18aaaSAndroid Build Coastguard Worker    Args:
785*c2e18aaaSAndroid Build Coastguard Worker        package: A string of the package name.
786*c2e18aaaSAndroid Build Coastguard Worker        module_name: Optional. A string of the module name.
787*c2e18aaaSAndroid Build Coastguard Worker        rel_config: Optional. A string of rel path of config.
788*c2e18aaaSAndroid Build Coastguard Worker
789*c2e18aaaSAndroid Build Coastguard Worker    Returns:
790*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if found, else None.
791*c2e18aaaSAndroid Build Coastguard Worker    """
792*c2e18aaaSAndroid Build Coastguard Worker    _, methods = test_filter_utils.split_methods(package)
793*c2e18aaaSAndroid Build Coastguard Worker    if methods:
794*c2e18aaaSAndroid Build Coastguard Worker      raise atest_error.MethodWithoutClassError(
795*c2e18aaaSAndroid Build Coastguard Worker          '%s: Method filtering requires class' % (methods)
796*c2e18aaaSAndroid Build Coastguard Worker      )
797*c2e18aaaSAndroid Build Coastguard Worker    # Confirm that packages exists and get user input for multiples.
798*c2e18aaaSAndroid Build Coastguard Worker    if rel_config:
799*c2e18aaaSAndroid Build Coastguard Worker      search_dir = os.path.join(self.root_dir, os.path.dirname(rel_config))
800*c2e18aaaSAndroid Build Coastguard Worker    else:
801*c2e18aaaSAndroid Build Coastguard Worker      search_dir = self.root_dir
802*c2e18aaaSAndroid Build Coastguard Worker    package_paths = test_finder_utils.run_find_cmd(
803*c2e18aaaSAndroid Build Coastguard Worker        test_finder_utils.TestReferenceType.PACKAGE, search_dir, package
804*c2e18aaaSAndroid Build Coastguard Worker    )
805*c2e18aaaSAndroid Build Coastguard Worker    package_paths = package_paths if package_paths is not None else []
806*c2e18aaaSAndroid Build Coastguard Worker    # Package path will be the full path to the dir represented by package.
807*c2e18aaaSAndroid Build Coastguard Worker    if not package_paths:
808*c2e18aaaSAndroid Build Coastguard Worker      if not module_name:
809*c2e18aaaSAndroid Build Coastguard Worker        return None
810*c2e18aaaSAndroid Build Coastguard Worker      module_paths = self.module_info.get_paths(module_name)
811*c2e18aaaSAndroid Build Coastguard Worker      for rel_module_path in module_paths:
812*c2e18aaaSAndroid Build Coastguard Worker        package_paths.append(os.path.join(self.root_dir, rel_module_path))
813*c2e18aaaSAndroid Build Coastguard Worker    test_filter = frozenset([test_info.TestFilter(package, frozenset())])
814*c2e18aaaSAndroid Build Coastguard Worker    test_infos = []
815*c2e18aaaSAndroid Build Coastguard Worker    for package_path in package_paths:
816*c2e18aaaSAndroid Build Coastguard Worker      tinfo = self._get_test_infos(
817*c2e18aaaSAndroid Build Coastguard Worker          package_path, rel_config, module_name, test_filter
818*c2e18aaaSAndroid Build Coastguard Worker      )
819*c2e18aaaSAndroid Build Coastguard Worker      if tinfo:
820*c2e18aaaSAndroid Build Coastguard Worker        test_infos.extend(tinfo)
821*c2e18aaaSAndroid Build Coastguard Worker    return test_infos if test_infos else None
822*c2e18aaaSAndroid Build Coastguard Worker
823*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_module_and_package(self, module_package):
824*c2e18aaaSAndroid Build Coastguard Worker    """Find the test info given a MODULE:PACKAGE string.
825*c2e18aaaSAndroid Build Coastguard Worker
826*c2e18aaaSAndroid Build Coastguard Worker    Args:
827*c2e18aaaSAndroid Build Coastguard Worker        module_package: A string of form MODULE:PACKAGE
828*c2e18aaaSAndroid Build Coastguard Worker
829*c2e18aaaSAndroid Build Coastguard Worker    Returns:
830*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if found, else None.
831*c2e18aaaSAndroid Build Coastguard Worker    """
832*c2e18aaaSAndroid Build Coastguard Worker    parse_result = test_finder_utils.parse_test_reference(module_package)
833*c2e18aaaSAndroid Build Coastguard Worker    if not parse_result:
834*c2e18aaaSAndroid Build Coastguard Worker      return None
835*c2e18aaaSAndroid Build Coastguard Worker    module_name = parse_result['module_name']
836*c2e18aaaSAndroid Build Coastguard Worker    package = parse_result['pkg_class_name']
837*c2e18aaaSAndroid Build Coastguard Worker    method = parse_result.get('method_name', '')
838*c2e18aaaSAndroid Build Coastguard Worker    if method:
839*c2e18aaaSAndroid Build Coastguard Worker      package = package + '#' + method
840*c2e18aaaSAndroid Build Coastguard Worker
841*c2e18aaaSAndroid Build Coastguard Worker    # module_infos is a list with at most 1 element.
842*c2e18aaaSAndroid Build Coastguard Worker    module_infos = self.find_test_by_module_name(module_name)
843*c2e18aaaSAndroid Build Coastguard Worker    module_info = module_infos[0] if module_infos else None
844*c2e18aaaSAndroid Build Coastguard Worker    if not module_info:
845*c2e18aaaSAndroid Build Coastguard Worker      return None
846*c2e18aaaSAndroid Build Coastguard Worker    return self.find_test_by_package_name(
847*c2e18aaaSAndroid Build Coastguard Worker        package,
848*c2e18aaaSAndroid Build Coastguard Worker        module_info.test_name,
849*c2e18aaaSAndroid Build Coastguard Worker        module_info.data.get(constants.TI_REL_CONFIG),
850*c2e18aaaSAndroid Build Coastguard Worker    )
851*c2e18aaaSAndroid Build Coastguard Worker
852*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_path(self, rel_path: str) -> List[test_info.TestInfo]:
853*c2e18aaaSAndroid Build Coastguard Worker    """Find the first test info matching the given path.
854*c2e18aaaSAndroid Build Coastguard Worker
855*c2e18aaaSAndroid Build Coastguard Worker    Strategy:
856*c2e18aaaSAndroid Build Coastguard Worker        path_to_java_file --> Resolve to CLASS
857*c2e18aaaSAndroid Build Coastguard Worker        path_to_cc_file --> Resolve to CC CLASS
858*c2e18aaaSAndroid Build Coastguard Worker        path_to_module_file -> Resolve to MODULE
859*c2e18aaaSAndroid Build Coastguard Worker        path_to_module_dir -> Resolve to MODULE
860*c2e18aaaSAndroid Build Coastguard Worker        path_to_dir_with_class_files--> Resolve to PACKAGE
861*c2e18aaaSAndroid Build Coastguard Worker        path_to_any_other_dir --> Resolve as MODULE
862*c2e18aaaSAndroid Build Coastguard Worker
863*c2e18aaaSAndroid Build Coastguard Worker    Args:
864*c2e18aaaSAndroid Build Coastguard Worker        rel_path: A string of the relative path to $BUILD_TOP.
865*c2e18aaaSAndroid Build Coastguard Worker
866*c2e18aaaSAndroid Build Coastguard Worker    Returns:
867*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if test found, else None
868*c2e18aaaSAndroid Build Coastguard Worker    """
869*c2e18aaaSAndroid Build Coastguard Worker    logging.debug('Finding test by path: %s', rel_path)
870*c2e18aaaSAndroid Build Coastguard Worker    path, methods = test_filter_utils.split_methods(rel_path)
871*c2e18aaaSAndroid Build Coastguard Worker    # create absolute path from cwd and remove symbolic links
872*c2e18aaaSAndroid Build Coastguard Worker    path = os.path.realpath(path)
873*c2e18aaaSAndroid Build Coastguard Worker    if not os.path.exists(path):
874*c2e18aaaSAndroid Build Coastguard Worker      return None
875*c2e18aaaSAndroid Build Coastguard Worker    if methods and not test_finder_utils.has_method_in_file(path, methods):
876*c2e18aaaSAndroid Build Coastguard Worker      return None
877*c2e18aaaSAndroid Build Coastguard Worker    dir_path, _ = test_finder_utils.get_dir_path_and_filename(path)
878*c2e18aaaSAndroid Build Coastguard Worker    # Module/Class
879*c2e18aaaSAndroid Build Coastguard Worker    rel_module_dir = test_finder_utils.find_parent_module_dir(
880*c2e18aaaSAndroid Build Coastguard Worker        self.root_dir, dir_path, self.module_info
881*c2e18aaaSAndroid Build Coastguard Worker    )
882*c2e18aaaSAndroid Build Coastguard Worker
883*c2e18aaaSAndroid Build Coastguard Worker    # If the input file path does not belong to a module(by searching
884*c2e18aaaSAndroid Build Coastguard Worker    # upwards to the build_top), check whether it belongs to the dependency
885*c2e18aaaSAndroid Build Coastguard Worker    # of modules.
886*c2e18aaaSAndroid Build Coastguard Worker    if not rel_module_dir:
887*c2e18aaaSAndroid Build Coastguard Worker      testable_modules = self.module_info.get_modules_by_include_deps(
888*c2e18aaaSAndroid Build Coastguard Worker          self.module_info.get_modules_by_path_in_srcs(rel_path),
889*c2e18aaaSAndroid Build Coastguard Worker          testable_module_only=True,
890*c2e18aaaSAndroid Build Coastguard Worker      )
891*c2e18aaaSAndroid Build Coastguard Worker      if testable_modules:
892*c2e18aaaSAndroid Build Coastguard Worker        test_filter = self._get_test_info_filter(
893*c2e18aaaSAndroid Build Coastguard Worker            path, methods, rel_module_dir=rel_module_dir
894*c2e18aaaSAndroid Build Coastguard Worker        )
895*c2e18aaaSAndroid Build Coastguard Worker        tinfos = []
896*c2e18aaaSAndroid Build Coastguard Worker        for testable_module in testable_modules:
897*c2e18aaaSAndroid Build Coastguard Worker          rel_config = os.path.join(
898*c2e18aaaSAndroid Build Coastguard Worker              self.module_info.get_paths(testable_module)[0],
899*c2e18aaaSAndroid Build Coastguard Worker              constants.MODULE_CONFIG,
900*c2e18aaaSAndroid Build Coastguard Worker          )
901*c2e18aaaSAndroid Build Coastguard Worker          tinfos.extend(
902*c2e18aaaSAndroid Build Coastguard Worker              self._get_test_infos(
903*c2e18aaaSAndroid Build Coastguard Worker                  path, rel_config, testable_module, test_filter
904*c2e18aaaSAndroid Build Coastguard Worker              )
905*c2e18aaaSAndroid Build Coastguard Worker          )
906*c2e18aaaSAndroid Build Coastguard Worker        metrics.LocalDetectEvent(
907*c2e18aaaSAndroid Build Coastguard Worker            detect_type=DetectType.FIND_TEST_IN_DEPS, result=1
908*c2e18aaaSAndroid Build Coastguard Worker        )
909*c2e18aaaSAndroid Build Coastguard Worker        return tinfos
910*c2e18aaaSAndroid Build Coastguard Worker
911*c2e18aaaSAndroid Build Coastguard Worker    if not rel_module_dir:
912*c2e18aaaSAndroid Build Coastguard Worker      # Try to find unit-test for input path.
913*c2e18aaaSAndroid Build Coastguard Worker      path = os.path.relpath(
914*c2e18aaaSAndroid Build Coastguard Worker          os.path.realpath(rel_path),
915*c2e18aaaSAndroid Build Coastguard Worker          os.environ.get(constants.ANDROID_BUILD_TOP, ''),
916*c2e18aaaSAndroid Build Coastguard Worker      )
917*c2e18aaaSAndroid Build Coastguard Worker      unit_tests = test_finder_utils.find_host_unit_tests(
918*c2e18aaaSAndroid Build Coastguard Worker          self.module_info, path
919*c2e18aaaSAndroid Build Coastguard Worker      )
920*c2e18aaaSAndroid Build Coastguard Worker      if unit_tests:
921*c2e18aaaSAndroid Build Coastguard Worker        tinfos = []
922*c2e18aaaSAndroid Build Coastguard Worker        for unit_test in unit_tests:
923*c2e18aaaSAndroid Build Coastguard Worker          tinfo = self._get_test_infos(
924*c2e18aaaSAndroid Build Coastguard Worker              path, constants.MODULE_CONFIG, unit_test, frozenset()
925*c2e18aaaSAndroid Build Coastguard Worker          )
926*c2e18aaaSAndroid Build Coastguard Worker          if tinfo:
927*c2e18aaaSAndroid Build Coastguard Worker            tinfos.extend(tinfo)
928*c2e18aaaSAndroid Build Coastguard Worker        return tinfos
929*c2e18aaaSAndroid Build Coastguard Worker      return None
930*c2e18aaaSAndroid Build Coastguard Worker    rel_config = os.path.join(rel_module_dir, constants.MODULE_CONFIG)
931*c2e18aaaSAndroid Build Coastguard Worker    test_filter = self._get_test_info_filter(
932*c2e18aaaSAndroid Build Coastguard Worker        path, methods, rel_module_dir=rel_module_dir
933*c2e18aaaSAndroid Build Coastguard Worker    )
934*c2e18aaaSAndroid Build Coastguard Worker    return self._get_test_infos(path, rel_config, None, test_filter)
935*c2e18aaaSAndroid Build Coastguard Worker
936*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_cc_class_name(
937*c2e18aaaSAndroid Build Coastguard Worker      self, class_name, module_name=None, rel_config=None
938*c2e18aaaSAndroid Build Coastguard Worker  ):
939*c2e18aaaSAndroid Build Coastguard Worker    """Find test files given a cc class name.
940*c2e18aaaSAndroid Build Coastguard Worker
941*c2e18aaaSAndroid Build Coastguard Worker    If module_name and rel_config not given, test will be determined
942*c2e18aaaSAndroid Build Coastguard Worker    by looking up the tree for files which has input class.
943*c2e18aaaSAndroid Build Coastguard Worker
944*c2e18aaaSAndroid Build Coastguard Worker    Args:
945*c2e18aaaSAndroid Build Coastguard Worker        class_name: A string of the test's class name.
946*c2e18aaaSAndroid Build Coastguard Worker        module_name: Optional. A string of the module name to use.
947*c2e18aaaSAndroid Build Coastguard Worker        rel_config: Optional. A string of module dir no-absolute to repo root.
948*c2e18aaaSAndroid Build Coastguard Worker
949*c2e18aaaSAndroid Build Coastguard Worker    Returns:
950*c2e18aaaSAndroid Build Coastguard Worker        A list of populated TestInfo namedtuple if test found, else None.
951*c2e18aaaSAndroid Build Coastguard Worker    """
952*c2e18aaaSAndroid Build Coastguard Worker    # Check if class_name is prepended with file name. If so, trim the
953*c2e18aaaSAndroid Build Coastguard Worker    # prefix and keep only the class_name.
954*c2e18aaaSAndroid Build Coastguard Worker    if '.' in class_name:
955*c2e18aaaSAndroid Build Coastguard Worker      # (b/202764540) Strip prefixes of a cc class.
956*c2e18aaaSAndroid Build Coastguard Worker      # Assume the class name has a format of file_name.class_name
957*c2e18aaaSAndroid Build Coastguard Worker      class_name = class_name[class_name.rindex('.') + 1 :]
958*c2e18aaaSAndroid Build Coastguard Worker      atest_utils.print_and_log_info(
959*c2e18aaaSAndroid Build Coastguard Worker          'Search with updated class name: %s', class_name
960*c2e18aaaSAndroid Build Coastguard Worker      )
961*c2e18aaaSAndroid Build Coastguard Worker    return self.find_test_by_class_name(
962*c2e18aaaSAndroid Build Coastguard Worker        class_name, module_name, rel_config, is_native_test=True
963*c2e18aaaSAndroid Build Coastguard Worker    )
964*c2e18aaaSAndroid Build Coastguard Worker
965*c2e18aaaSAndroid Build Coastguard Worker  def get_testable_modules_with_ld(self, user_input, ld_range=0):
966*c2e18aaaSAndroid Build Coastguard Worker    """Calculate the edit distances of the input and testable modules.
967*c2e18aaaSAndroid Build Coastguard Worker
968*c2e18aaaSAndroid Build Coastguard Worker    The user input will be calculated across all testable modules and
969*c2e18aaaSAndroid Build Coastguard Worker    results in integers generated by Levenshtein Distance algorithm.
970*c2e18aaaSAndroid Build Coastguard Worker    To increase the speed of the calculation, a bound can be applied to
971*c2e18aaaSAndroid Build Coastguard Worker    this method to prevent from calculating every testable modules.
972*c2e18aaaSAndroid Build Coastguard Worker
973*c2e18aaaSAndroid Build Coastguard Worker    Guessing from typos, e.g. atest atest_unitests, implies a tangible range
974*c2e18aaaSAndroid Build Coastguard Worker    of length that Atest only needs to search within it, and the default of
975*c2e18aaaSAndroid Build Coastguard Worker    the bound is 2.
976*c2e18aaaSAndroid Build Coastguard Worker
977*c2e18aaaSAndroid Build Coastguard Worker    Guessing from keywords however, e.g. atest --search Camera, means that
978*c2e18aaaSAndroid Build Coastguard Worker    the uncertainty of the module name is way higher, and Atest should walk
979*c2e18aaaSAndroid Build Coastguard Worker    through all testable modules and return the highest possibilities.
980*c2e18aaaSAndroid Build Coastguard Worker
981*c2e18aaaSAndroid Build Coastguard Worker    Args:
982*c2e18aaaSAndroid Build Coastguard Worker        user_input: A string of the user input.
983*c2e18aaaSAndroid Build Coastguard Worker        ld_range: An integer that range the searching scope. If the length of
984*c2e18aaaSAndroid Build Coastguard Worker          user_input is 10, then Atest will calculate modules of which length is
985*c2e18aaaSAndroid Build Coastguard Worker          between 8 and 12. 0 is equivalent to unlimited.
986*c2e18aaaSAndroid Build Coastguard Worker
987*c2e18aaaSAndroid Build Coastguard Worker    Returns:
988*c2e18aaaSAndroid Build Coastguard Worker        A List of LDs and possible module names. If the user_input is "fax",
989*c2e18aaaSAndroid Build Coastguard Worker        the output will be like:
990*c2e18aaaSAndroid Build Coastguard Worker        [[2, "fog"], [2, "Fix"], [4, "duck"], [7, "Duckies"]]
991*c2e18aaaSAndroid Build Coastguard Worker
992*c2e18aaaSAndroid Build Coastguard Worker        Which means the most lilely names of "fax" are fog and Fix(LD=2),
993*c2e18aaaSAndroid Build Coastguard Worker        while Dickies is the most unlikely one(LD=7).
994*c2e18aaaSAndroid Build Coastguard Worker    """
995*c2e18aaaSAndroid Build Coastguard Worker    atest_utils.colorful_print(
996*c2e18aaaSAndroid Build Coastguard Worker        '\nSearching for similar module names using fuzzy search...',
997*c2e18aaaSAndroid Build Coastguard Worker        constants.CYAN,
998*c2e18aaaSAndroid Build Coastguard Worker    )
999*c2e18aaaSAndroid Build Coastguard Worker    search_start = time.time()
1000*c2e18aaaSAndroid Build Coastguard Worker    testable_modules = sorted(self.module_info.get_testable_modules(), key=len)
1001*c2e18aaaSAndroid Build Coastguard Worker    lower_bound = len(user_input) - ld_range
1002*c2e18aaaSAndroid Build Coastguard Worker    upper_bound = len(user_input) + ld_range
1003*c2e18aaaSAndroid Build Coastguard Worker    testable_modules_with_ld = []
1004*c2e18aaaSAndroid Build Coastguard Worker    for module_name in testable_modules:
1005*c2e18aaaSAndroid Build Coastguard Worker      # Dispose those too short or too lengthy.
1006*c2e18aaaSAndroid Build Coastguard Worker      if ld_range != 0:
1007*c2e18aaaSAndroid Build Coastguard Worker        if len(module_name) < lower_bound:
1008*c2e18aaaSAndroid Build Coastguard Worker          continue
1009*c2e18aaaSAndroid Build Coastguard Worker        if len(module_name) > upper_bound:
1010*c2e18aaaSAndroid Build Coastguard Worker          break
1011*c2e18aaaSAndroid Build Coastguard Worker      testable_modules_with_ld.append([
1012*c2e18aaaSAndroid Build Coastguard Worker          test_finder_utils.get_levenshtein_distance(user_input, module_name),
1013*c2e18aaaSAndroid Build Coastguard Worker          module_name,
1014*c2e18aaaSAndroid Build Coastguard Worker      ])
1015*c2e18aaaSAndroid Build Coastguard Worker    search_duration = time.time() - search_start
1016*c2e18aaaSAndroid Build Coastguard Worker    logging.debug('Fuzzy search took %ss', search_duration)
1017*c2e18aaaSAndroid Build Coastguard Worker    metrics.LocalDetectEvent(
1018*c2e18aaaSAndroid Build Coastguard Worker        detect_type=DetectType.FUZZY_SEARCH_TIME, result=round(search_duration)
1019*c2e18aaaSAndroid Build Coastguard Worker    )
1020*c2e18aaaSAndroid Build Coastguard Worker    return testable_modules_with_ld
1021*c2e18aaaSAndroid Build Coastguard Worker
1022*c2e18aaaSAndroid Build Coastguard Worker  def get_fuzzy_searching_results(self, user_input):
1023*c2e18aaaSAndroid Build Coastguard Worker    """Give results which have no more than allowance of edit distances.
1024*c2e18aaaSAndroid Build Coastguard Worker
1025*c2e18aaaSAndroid Build Coastguard Worker    Args:
1026*c2e18aaaSAndroid Build Coastguard Worker        user_input: the target module name for fuzzy searching.
1027*c2e18aaaSAndroid Build Coastguard Worker
1028*c2e18aaaSAndroid Build Coastguard Worker    Returns:
1029*c2e18aaaSAndroid Build Coastguard Worker        A list of guessed modules.
1030*c2e18aaaSAndroid Build Coastguard Worker    """
1031*c2e18aaaSAndroid Build Coastguard Worker    modules_with_ld = self.get_testable_modules_with_ld(
1032*c2e18aaaSAndroid Build Coastguard Worker        user_input, ld_range=constants.LD_RANGE
1033*c2e18aaaSAndroid Build Coastguard Worker    )
1034*c2e18aaaSAndroid Build Coastguard Worker    guessed_modules = []
1035*c2e18aaaSAndroid Build Coastguard Worker    for distance_, module_ in modules_with_ld:
1036*c2e18aaaSAndroid Build Coastguard Worker      if distance_ <= abs(constants.LD_RANGE):
1037*c2e18aaaSAndroid Build Coastguard Worker        guessed_modules.append(module_)
1038*c2e18aaaSAndroid Build Coastguard Worker    return guessed_modules
1039*c2e18aaaSAndroid Build Coastguard Worker
1040*c2e18aaaSAndroid Build Coastguard Worker  def find_test_by_config_name(self, config_name):
1041*c2e18aaaSAndroid Build Coastguard Worker    """Find test for the given config name.
1042*c2e18aaaSAndroid Build Coastguard Worker
1043*c2e18aaaSAndroid Build Coastguard Worker    Args:
1044*c2e18aaaSAndroid Build Coastguard Worker        config_name: A string of the test's config name.
1045*c2e18aaaSAndroid Build Coastguard Worker
1046*c2e18aaaSAndroid Build Coastguard Worker    Returns:
1047*c2e18aaaSAndroid Build Coastguard Worker        A list that includes only 1 populated TestInfo namedtuple
1048*c2e18aaaSAndroid Build Coastguard Worker        if found, otherwise None.
1049*c2e18aaaSAndroid Build Coastguard Worker    """
1050*c2e18aaaSAndroid Build Coastguard Worker    for module_name, mod_info in self.module_info.name_to_module_info.items():
1051*c2e18aaaSAndroid Build Coastguard Worker      test_configs = mod_info.get(constants.MODULE_TEST_CONFIG, [])
1052*c2e18aaaSAndroid Build Coastguard Worker      for test_config in test_configs:
1053*c2e18aaaSAndroid Build Coastguard Worker        test_config_name = os.path.splitext(os.path.basename(test_config))[0]
1054*c2e18aaaSAndroid Build Coastguard Worker        if test_config_name == config_name:
1055*c2e18aaaSAndroid Build Coastguard Worker          tinfo = test_info.TestInfo(
1056*c2e18aaaSAndroid Build Coastguard Worker              test_name=test_config_name,
1057*c2e18aaaSAndroid Build Coastguard Worker              test_runner=self._TEST_RUNNER,
1058*c2e18aaaSAndroid Build Coastguard Worker              build_targets=self._get_build_targets(module_name, test_config),
1059*c2e18aaaSAndroid Build Coastguard Worker              data={
1060*c2e18aaaSAndroid Build Coastguard Worker                  constants.TI_REL_CONFIG: test_config,
1061*c2e18aaaSAndroid Build Coastguard Worker                  constants.TI_FILTER: frozenset(),
1062*c2e18aaaSAndroid Build Coastguard Worker              },
1063*c2e18aaaSAndroid Build Coastguard Worker              compatibility_suites=mod_info.get(
1064*c2e18aaaSAndroid Build Coastguard Worker                  constants.MODULE_COMPATIBILITY_SUITES, []
1065*c2e18aaaSAndroid Build Coastguard Worker              ),
1066*c2e18aaaSAndroid Build Coastguard Worker          )
1067*c2e18aaaSAndroid Build Coastguard Worker          test_config_path = os.path.join(self.root_dir, test_config)
1068*c2e18aaaSAndroid Build Coastguard Worker          if test_finder_utils.need_aggregate_metrics_result(test_config_path):
1069*c2e18aaaSAndroid Build Coastguard Worker            tinfo.aggregate_metrics_result = True
1070*c2e18aaaSAndroid Build Coastguard Worker          if tinfo:
1071*c2e18aaaSAndroid Build Coastguard Worker            # There should have only one test_config with the same
1072*c2e18aaaSAndroid Build Coastguard Worker            # name in source tree.
1073*c2e18aaaSAndroid Build Coastguard Worker            return [tinfo]
1074*c2e18aaaSAndroid Build Coastguard Worker    return None
1075*c2e18aaaSAndroid Build Coastguard Worker
1076*c2e18aaaSAndroid Build Coastguard Worker  @staticmethod
1077*c2e18aaaSAndroid Build Coastguard Worker  def _is_comparted_src(path):
1078*c2e18aaaSAndroid Build Coastguard Worker    """Check if the input path need to match srcs information in module.
1079*c2e18aaaSAndroid Build Coastguard Worker
1080*c2e18aaaSAndroid Build Coastguard Worker    If path is a folder or android build file, we don't need to compart
1081*c2e18aaaSAndroid Build Coastguard Worker    with module's srcs.
1082*c2e18aaaSAndroid Build Coastguard Worker
1083*c2e18aaaSAndroid Build Coastguard Worker    Args:
1084*c2e18aaaSAndroid Build Coastguard Worker        path: A string of the test's path.
1085*c2e18aaaSAndroid Build Coastguard Worker
1086*c2e18aaaSAndroid Build Coastguard Worker    Returns:
1087*c2e18aaaSAndroid Build Coastguard Worker        True if input path need to match with module's src info, else False.
1088*c2e18aaaSAndroid Build Coastguard Worker    """
1089*c2e18aaaSAndroid Build Coastguard Worker    if os.path.isdir(path):
1090*c2e18aaaSAndroid Build Coastguard Worker      return False
1091*c2e18aaaSAndroid Build Coastguard Worker    if atest_utils.is_build_file(path):
1092*c2e18aaaSAndroid Build Coastguard Worker      return False
1093*c2e18aaaSAndroid Build Coastguard Worker    return True
1094*c2e18aaaSAndroid Build Coastguard Worker
1095*c2e18aaaSAndroid Build Coastguard Worker
1096*c2e18aaaSAndroid Build Coastguard Workerclass MainlineModuleFinder(ModuleFinder):
1097*c2e18aaaSAndroid Build Coastguard Worker  """Mainline Module finder class."""
1098*c2e18aaaSAndroid Build Coastguard Worker
1099*c2e18aaaSAndroid Build Coastguard Worker  NAME = 'MAINLINE_MODULE'
1100*c2e18aaaSAndroid Build Coastguard Worker
1101*c2e18aaaSAndroid Build Coastguard Worker  def __init__(self, module_info=None):
1102*c2e18aaaSAndroid Build Coastguard Worker    super().__init__()
1103