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