1*c2e18aaaSAndroid Build Coastguard Worker# Copyright 2019, 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"""Cache Finder class.""" 16*c2e18aaaSAndroid Build Coastguard Worker 17*c2e18aaaSAndroid Build Coastguard Workerimport logging 18*c2e18aaaSAndroid Build Coastguard Worker 19*c2e18aaaSAndroid Build Coastguard Workerfrom atest import atest_utils 20*c2e18aaaSAndroid Build Coastguard Workerfrom atest import constants 21*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_filter_utils 22*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_finder_base 23*c2e18aaaSAndroid Build Coastguard Workerfrom atest.test_finders import test_info 24*c2e18aaaSAndroid Build Coastguard Worker 25*c2e18aaaSAndroid Build Coastguard Worker 26*c2e18aaaSAndroid Build Coastguard Workerclass CacheFinder(test_finder_base.TestFinderBase): 27*c2e18aaaSAndroid Build Coastguard Worker """Cache Finder class.""" 28*c2e18aaaSAndroid Build Coastguard Worker 29*c2e18aaaSAndroid Build Coastguard Worker NAME = 'CACHE' 30*c2e18aaaSAndroid Build Coastguard Worker 31*c2e18aaaSAndroid Build Coastguard Worker def __init__(self, module_info=None): 32*c2e18aaaSAndroid Build Coastguard Worker super().__init__() 33*c2e18aaaSAndroid Build Coastguard Worker self.module_info = module_info 34*c2e18aaaSAndroid Build Coastguard Worker 35*c2e18aaaSAndroid Build Coastguard Worker def _is_latest_testinfos(self, test_infos): 36*c2e18aaaSAndroid Build Coastguard Worker """Check whether test_infos are up-to-date. 37*c2e18aaaSAndroid Build Coastguard Worker 38*c2e18aaaSAndroid Build Coastguard Worker Args: 39*c2e18aaaSAndroid Build Coastguard Worker test_infos: A list of TestInfo. 40*c2e18aaaSAndroid Build Coastguard Worker 41*c2e18aaaSAndroid Build Coastguard Worker Returns: 42*c2e18aaaSAndroid Build Coastguard Worker True if all keys in test_infos and TestInfo object are equal. 43*c2e18aaaSAndroid Build Coastguard Worker Otherwise, False. 44*c2e18aaaSAndroid Build Coastguard Worker """ 45*c2e18aaaSAndroid Build Coastguard Worker sorted_base_ti = sorted(vars(test_info.TestInfo(None, None, None)).keys()) 46*c2e18aaaSAndroid Build Coastguard Worker for cached_test_info in test_infos: 47*c2e18aaaSAndroid Build Coastguard Worker sorted_cache_ti = sorted(vars(cached_test_info).keys()) 48*c2e18aaaSAndroid Build Coastguard Worker if not sorted_cache_ti == sorted_base_ti: 49*c2e18aaaSAndroid Build Coastguard Worker logging.debug('test_info is not up-to-date.') 50*c2e18aaaSAndroid Build Coastguard Worker return False 51*c2e18aaaSAndroid Build Coastguard Worker return True 52*c2e18aaaSAndroid Build Coastguard Worker 53*c2e18aaaSAndroid Build Coastguard Worker def find_test_by_cache(self, test_reference): 54*c2e18aaaSAndroid Build Coastguard Worker """Find the matched test_infos in saved caches. 55*c2e18aaaSAndroid Build Coastguard Worker 56*c2e18aaaSAndroid Build Coastguard Worker Args: 57*c2e18aaaSAndroid Build Coastguard Worker test_reference: A string of the path to the test's file or dir. 58*c2e18aaaSAndroid Build Coastguard Worker 59*c2e18aaaSAndroid Build Coastguard Worker Returns: 60*c2e18aaaSAndroid Build Coastguard Worker A list of TestInfo namedtuple if cache found and is in latest 61*c2e18aaaSAndroid Build Coastguard Worker TestInfo format, else None. 62*c2e18aaaSAndroid Build Coastguard Worker """ 63*c2e18aaaSAndroid Build Coastguard Worker test_infos = atest_utils.load_test_info_cache(test_reference) 64*c2e18aaaSAndroid Build Coastguard Worker if test_infos and self._is_test_infos_valid(test_infos): 65*c2e18aaaSAndroid Build Coastguard Worker return test_infos 66*c2e18aaaSAndroid Build Coastguard Worker return None 67*c2e18aaaSAndroid Build Coastguard Worker 68*c2e18aaaSAndroid Build Coastguard Worker def _is_test_infos_valid(self, test_infos): 69*c2e18aaaSAndroid Build Coastguard Worker """Check if the given test_infos are valid. 70*c2e18aaaSAndroid Build Coastguard Worker 71*c2e18aaaSAndroid Build Coastguard Worker Args: 72*c2e18aaaSAndroid Build Coastguard Worker test_infos: A list of TestInfo. 73*c2e18aaaSAndroid Build Coastguard Worker 74*c2e18aaaSAndroid Build Coastguard Worker Returns: 75*c2e18aaaSAndroid Build Coastguard Worker True if test_infos are all valid. Otherwise, False. 76*c2e18aaaSAndroid Build Coastguard Worker """ 77*c2e18aaaSAndroid Build Coastguard Worker if not self._is_latest_testinfos(test_infos): 78*c2e18aaaSAndroid Build Coastguard Worker return False 79*c2e18aaaSAndroid Build Coastguard Worker for t_info in test_infos: 80*c2e18aaaSAndroid Build Coastguard Worker if t_info.test_runner == 'BazelTestRunner': 81*c2e18aaaSAndroid Build Coastguard Worker return False 82*c2e18aaaSAndroid Build Coastguard Worker if not self._is_test_path_valid(t_info): 83*c2e18aaaSAndroid Build Coastguard Worker return False 84*c2e18aaaSAndroid Build Coastguard Worker if not self._is_test_build_target_valid(t_info): 85*c2e18aaaSAndroid Build Coastguard Worker return False 86*c2e18aaaSAndroid Build Coastguard Worker if not self._is_test_filter_valid(t_info): 87*c2e18aaaSAndroid Build Coastguard Worker return False 88*c2e18aaaSAndroid Build Coastguard Worker return True 89*c2e18aaaSAndroid Build Coastguard Worker 90*c2e18aaaSAndroid Build Coastguard Worker def _is_test_path_valid(self, t_info): 91*c2e18aaaSAndroid Build Coastguard Worker """Check if test path is valid. 92*c2e18aaaSAndroid Build Coastguard Worker 93*c2e18aaaSAndroid Build Coastguard Worker Args: 94*c2e18aaaSAndroid Build Coastguard Worker t_info: TestInfo that has been filled out by a find method. 95*c2e18aaaSAndroid Build Coastguard Worker 96*c2e18aaaSAndroid Build Coastguard Worker Returns: 97*c2e18aaaSAndroid Build Coastguard Worker True if test path is valid. Otherwise, False. 98*c2e18aaaSAndroid Build Coastguard Worker """ 99*c2e18aaaSAndroid Build Coastguard Worker # For RoboTest it won't have 'MODULES-IN-' as build target. Treat test 100*c2e18aaaSAndroid Build Coastguard Worker # path is valid if cached_test_paths is None. 101*c2e18aaaSAndroid Build Coastguard Worker cached_test_paths = t_info.get_test_paths() 102*c2e18aaaSAndroid Build Coastguard Worker if cached_test_paths is None: 103*c2e18aaaSAndroid Build Coastguard Worker return True 104*c2e18aaaSAndroid Build Coastguard Worker current_test_paths = self.module_info.get_paths(t_info.test_name) 105*c2e18aaaSAndroid Build Coastguard Worker if not current_test_paths: 106*c2e18aaaSAndroid Build Coastguard Worker return False 107*c2e18aaaSAndroid Build Coastguard Worker formatted_paths = [p.replace('/', '-') for p in current_test_paths] 108*c2e18aaaSAndroid Build Coastguard Worker if sorted(cached_test_paths) != sorted(formatted_paths): 109*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Not a valid test path.') 110*c2e18aaaSAndroid Build Coastguard Worker return False 111*c2e18aaaSAndroid Build Coastguard Worker return True 112*c2e18aaaSAndroid Build Coastguard Worker 113*c2e18aaaSAndroid Build Coastguard Worker def _is_test_build_target_valid(self, t_info): 114*c2e18aaaSAndroid Build Coastguard Worker """Check if test build targets are valid. 115*c2e18aaaSAndroid Build Coastguard Worker 116*c2e18aaaSAndroid Build Coastguard Worker Args: 117*c2e18aaaSAndroid Build Coastguard Worker t_info: TestInfo that has been filled out by a find method. 118*c2e18aaaSAndroid Build Coastguard Worker 119*c2e18aaaSAndroid Build Coastguard Worker Returns: 120*c2e18aaaSAndroid Build Coastguard Worker True if test's build target is valid. Otherwise, False. 121*c2e18aaaSAndroid Build Coastguard Worker """ 122*c2e18aaaSAndroid Build Coastguard Worker # If the cached build target can be found in current module-info, then 123*c2e18aaaSAndroid Build Coastguard Worker # it is a valid build targets of the test. 124*c2e18aaaSAndroid Build Coastguard Worker for build_target in t_info.build_targets: 125*c2e18aaaSAndroid Build Coastguard Worker if str(build_target).startswith(constants.MODULES_IN): 126*c2e18aaaSAndroid Build Coastguard Worker continue 127*c2e18aaaSAndroid Build Coastguard Worker if not self.module_info.is_module(build_target): 128*c2e18aaaSAndroid Build Coastguard Worker logging.debug('%s is not a valid build target.', build_target) 129*c2e18aaaSAndroid Build Coastguard Worker return False 130*c2e18aaaSAndroid Build Coastguard Worker return True 131*c2e18aaaSAndroid Build Coastguard Worker 132*c2e18aaaSAndroid Build Coastguard Worker def _is_test_filter_valid(self, t_info): 133*c2e18aaaSAndroid Build Coastguard Worker """Check if test filter is valid. 134*c2e18aaaSAndroid Build Coastguard Worker 135*c2e18aaaSAndroid Build Coastguard Worker Args: 136*c2e18aaaSAndroid Build Coastguard Worker t_info: TestInfo that has been filled out by a find method. 137*c2e18aaaSAndroid Build Coastguard Worker 138*c2e18aaaSAndroid Build Coastguard Worker Returns: 139*c2e18aaaSAndroid Build Coastguard Worker True if test filter is valid. Otherwise, False. 140*c2e18aaaSAndroid Build Coastguard Worker """ 141*c2e18aaaSAndroid Build Coastguard Worker test_filters = t_info.data.get(constants.TI_FILTER, []) 142*c2e18aaaSAndroid Build Coastguard Worker if not test_filters: 143*c2e18aaaSAndroid Build Coastguard Worker return True 144*c2e18aaaSAndroid Build Coastguard Worker for test_filter in test_filters: 145*c2e18aaaSAndroid Build Coastguard Worker # Check if the class filter is under current module. 146*c2e18aaaSAndroid Build Coastguard Worker # TODO: (b/172260100) The test_name may not be inevitably equal to 147*c2e18aaaSAndroid Build Coastguard Worker # the module_name. 148*c2e18aaaSAndroid Build Coastguard Worker if not self._is_class_in_module(t_info.test_name, test_filter.class_name): 149*c2e18aaaSAndroid Build Coastguard Worker logging.debug('Not a valid test filter.') 150*c2e18aaaSAndroid Build Coastguard Worker return False 151*c2e18aaaSAndroid Build Coastguard Worker return True 152*c2e18aaaSAndroid Build Coastguard Worker 153*c2e18aaaSAndroid Build Coastguard Worker def _is_class_in_module(self, module_name, filter_class): 154*c2e18aaaSAndroid Build Coastguard Worker """Check if input class is part of input module. 155*c2e18aaaSAndroid Build Coastguard Worker 156*c2e18aaaSAndroid Build Coastguard Worker Args: 157*c2e18aaaSAndroid Build Coastguard Worker module_name: A string of the module name of the test. 158*c2e18aaaSAndroid Build Coastguard Worker filter_class: A string of the class name field of TI_FILTER. 159*c2e18aaaSAndroid Build Coastguard Worker 160*c2e18aaaSAndroid Build Coastguard Worker Returns: 161*c2e18aaaSAndroid Build Coastguard Worker True if input filter_class is in the input module. Otherwise, False. 162*c2e18aaaSAndroid Build Coastguard Worker """ 163*c2e18aaaSAndroid Build Coastguard Worker mod_info = self.module_info.get_module_info(module_name) 164*c2e18aaaSAndroid Build Coastguard Worker if not mod_info: 165*c2e18aaaSAndroid Build Coastguard Worker return False 166*c2e18aaaSAndroid Build Coastguard Worker module_srcs = mod_info.get(constants.MODULE_SRCS, []) 167*c2e18aaaSAndroid Build Coastguard Worker # If module didn't have src information treat the cached filter still 168*c2e18aaaSAndroid Build Coastguard Worker # valid. Remove this after all java srcs could be found in module-info. 169*c2e18aaaSAndroid Build Coastguard Worker if not module_srcs: 170*c2e18aaaSAndroid Build Coastguard Worker return True 171*c2e18aaaSAndroid Build Coastguard Worker 172*c2e18aaaSAndroid Build Coastguard Worker for src_path in module_srcs: 173*c2e18aaaSAndroid Build Coastguard Worker abs_src_path = atest_utils.get_build_top(src_path) 174*c2e18aaaSAndroid Build Coastguard Worker if constants.CC_EXT_RE.match(src_path): 175*c2e18aaaSAndroid Build Coastguard Worker # TODO: (b/172260100) Also check for CC. 176*c2e18aaaSAndroid Build Coastguard Worker return True 177*c2e18aaaSAndroid Build Coastguard Worker else: 178*c2e18aaaSAndroid Build Coastguard Worker full_class_name = test_filter_utils.get_fully_qualified_class_name( 179*c2e18aaaSAndroid Build Coastguard Worker abs_src_path 180*c2e18aaaSAndroid Build Coastguard Worker ) 181*c2e18aaaSAndroid Build Coastguard Worker package_name = test_filter_utils.get_package_name(abs_src_path) 182*c2e18aaaSAndroid Build Coastguard Worker if filter_class == full_class_name or filter_class == package_name: 183*c2e18aaaSAndroid Build Coastguard Worker return True 184*c2e18aaaSAndroid Build Coastguard Worker return False 185