blob: a33da2db4647c6eae1fa3fa2500e24c1e72e9c62 [file] [log] [blame]
# Copyright 2018, The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Suite Plan Finder class.
"""
import logging
import os
import re
# pylint: disable=import-error
import constants
from test_finders import test_finder_base
from test_finders import test_finder_utils
from test_finders import test_info
from test_runners import suite_plan_test_runner
_SUITE_PLAN_NAME_RE = re.compile(r'^.*\/(?P<suite>.*)-tradefed\/res\/config\/'
r'(?P<suite_plan_name>.*).xml$')
class SuitePlanFinder(test_finder_base.TestFinderBase):
"""Suite Plan Finder class."""
NAME = 'SUITE_PLAN'
_SUITE_PLAN_TEST_RUNNER = suite_plan_test_runner.SuitePlanTestRunner.NAME
def __init__(self, module_info=None):
super(SuitePlanFinder, self).__init__()
self.root_dir = os.environ.get(constants.ANDROID_BUILD_TOP)
self.mod_info = module_info
self.suite_plan_dirs = self._get_suite_plan_dirs()
def _get_mod_paths(self, module_name):
"""Return the paths of the given module name."""
if self.mod_info:
return self.mod_info.get_paths(module_name)
return []
def _get_suite_plan_dirs(self):
"""Get suite plan dirs from MODULE_INFO based on targets.
Strategy:
Search module-info.json using SUITE_PLANS to get all the suite
plan dirs.
Returns:
A tuple of lists of strings of suite plan dir rel to repo root.
None if the path can not be found in module-info.json.
"""
return [d for x in constants.SUITE_PLANS for d in
self._get_mod_paths(x+'-tradefed') if d is not None]
def _get_test_info_from_path(self, path, suite_name=None):
"""Get the test info from the result of using regular expression
matching with the give path.
Args:
path: A string of the test's absolute or relative path.
suite_name: A string of the suite name.
Returns:
A populated TestInfo namedtuple if regular expression
matches, else None.
"""
# Don't use names that simply match the path,
# must be the actual name used by *TS to run the test.
match = _SUITE_PLAN_NAME_RE.match(path)
if not match:
logging.error('Suite plan test outside config dir: %s', path)
return None
suite = match.group('suite')
suite_plan_name = match.group('suite_plan_name')
if suite_name:
if suite_plan_name != suite_name:
logging.warn('Input (%s) not valid suite plan name, '
'did you mean: %s?', suite_name, suite_plan_name)
return None
return test_info.TestInfo(
test_name=suite_plan_name,
test_runner=self._SUITE_PLAN_TEST_RUNNER,
build_targets=set([suite]),
suite=suite)
def find_test_by_suite_path(self, suite_path):
"""Find the first test info matching the given path.
Strategy:
If suite_path is to file --> Return TestInfo if the file
exists in the suite plan dirs, else return None.
If suite_path is to dir --> Return None
Args:
suite_path: A string of the path to the test's file or dir.
Returns:
A list of populated TestInfo namedtuple if test found, else None.
This is a list with at most 1 element.
"""
path, _ = test_finder_utils.split_methods(suite_path)
# Make sure we're looking for a config.
if not path.endswith('.xml'):
return None
path = os.path.realpath(path)
suite_plan_dir = test_finder_utils.get_int_dir_from_path(
path, self.suite_plan_dirs)
if suite_plan_dir:
rel_config = os.path.relpath(path, self.root_dir)
return [self._get_test_info_from_path(rel_config)]
return None
def find_test_by_suite_name(self, suite_name):
"""Find the test for the given suite name.
Strategy:
If suite_name is cts --> Return TestInfo to indicate suite runner
to make cts and run test using cts-tradefed.
If suite_name is cts-common --> Return TestInfo to indicate suite
runner to make cts and run test using cts-tradefed if file exists
in the suite plan dirs, else return None.
Args:
suite_name: A string of suite name.
Returns:
A list of populated TestInfo namedtuple if suite_name matches
a suite in constants.SUITE_PLAN, else check if the file
existing in the suite plan dirs, else return None.
"""
logging.debug('Finding test by suite: %s', suite_name)
test_infos = []
if suite_name in constants.SUITE_PLANS:
test_infos.append(test_info.TestInfo(
test_name=suite_name,
test_runner=self._SUITE_PLAN_TEST_RUNNER,
build_targets=set([suite_name]),
suite=suite_name))
else:
test_files = test_finder_utils.search_integration_dirs(
suite_name, self.suite_plan_dirs)
if not test_files:
return None
for test_file in test_files:
_test_info = self._get_test_info_from_path(test_file, suite_name)
if _test_info:
test_infos.append(_test_info)
return test_infos