• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2018, The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15"""
16Suite Plan Finder class.
17"""
18
19import logging
20import os
21import re
22
23# pylint: disable=import-error
24import constants
25from test_finders import test_finder_base
26from test_finders import test_finder_utils
27from test_finders import test_info
28from test_runners import suite_plan_test_runner
29
30_SUITE_PLAN_NAME_RE = re.compile(r'^.*\/(?P<suite>.*)-tradefed\/res\/config\/'
31                                 r'(?P<suite_plan_name>.*).xml$')
32
33
34class SuitePlanFinder(test_finder_base.TestFinderBase):
35    """Suite Plan Finder class."""
36    NAME = 'SUITE_PLAN'
37    _SUITE_PLAN_TEST_RUNNER = suite_plan_test_runner.SuitePlanTestRunner.NAME
38
39    def __init__(self, module_info=None):
40        super(SuitePlanFinder, self).__init__()
41        self.root_dir = os.environ.get(constants.ANDROID_BUILD_TOP)
42        self.mod_info = module_info
43        self.suite_plan_dirs = self._get_suite_plan_dirs()
44
45    def _get_mod_paths(self, module_name):
46        """Return the paths of the given module name."""
47        if self.mod_info:
48            return self.mod_info.get_paths(module_name)
49        return []
50
51    def _get_suite_plan_dirs(self):
52        """Get suite plan dirs from MODULE_INFO based on targets.
53
54        Strategy:
55            Search module-info.json using SUITE_PLANS to get all the suite
56            plan dirs.
57
58        Returns:
59            A tuple of lists of strings of suite plan dir rel to repo root.
60            None if the path can not be found in module-info.json.
61        """
62        return [d for x in constants.SUITE_PLANS for d in
63                self._get_mod_paths(x+'-tradefed') if d is not None]
64
65    def _get_test_info_from_path(self, path, suite_name=None):
66        """Get the test info from the result of using regular expression
67        matching with the give path.
68
69        Args:
70            path: A string of the test's absolute or relative path.
71            suite_name: A string of the suite name.
72
73        Returns:
74            A populated TestInfo namedtuple if regular expression
75            matches, else None.
76        """
77        # Don't use names that simply match the path,
78        # must be the actual name used by *TS to run the test.
79        match = _SUITE_PLAN_NAME_RE.match(path)
80        if not match:
81            logging.error('Suite plan test outside config dir: %s', path)
82            return None
83        suite = match.group('suite')
84        suite_plan_name = match.group('suite_plan_name')
85        if suite_name:
86            if suite_plan_name != suite_name:
87                logging.warn('Input (%s) not valid suite plan name, '
88                             'did you mean: %s?', suite_name, suite_plan_name)
89                return None
90        return test_info.TestInfo(
91            test_name=suite_plan_name,
92            test_runner=self._SUITE_PLAN_TEST_RUNNER,
93            build_targets=set([suite]),
94            suite=suite)
95
96    def find_test_by_suite_path(self, suite_path):
97        """Find the first test info matching the given path.
98
99        Strategy:
100            If suite_path is to file --> Return TestInfo if the file
101            exists in the suite plan dirs, else return None.
102            If suite_path is to dir --> Return None
103
104        Args:
105            suite_path: A string of the path to the test's file or dir.
106
107        Returns:
108            A populated TestInfo namedtuple if test found, else None.
109        """
110        path, _ = test_finder_utils.split_methods(suite_path)
111        # Make sure we're looking for a config.
112        if not path.endswith('.xml'):
113            return None
114        path = os.path.realpath(path)
115        suite_plan_dir = test_finder_utils.get_int_dir_from_path(
116            path, self.suite_plan_dirs)
117        if suite_plan_dir:
118            rel_config = os.path.relpath(path, self.root_dir)
119            return self._get_test_info_from_path(rel_config)
120        return None
121
122    def find_test_by_suite_name(self, suite_name):
123        """Find the test for the given suite name.
124
125        Strategy:
126            If suite_name is cts --> Return TestInfo to indicate suite runner
127            to make cts and run test using cts-tradefed.
128            If suite_name is cts-common --> Return TestInfo to indicate suite
129            runner to make cts and run test using cts-tradefed if file exists
130            in the suite plan dirs, else return None.
131
132        Args:
133            suite_name: A string of suite name.
134
135        Returns:
136            A populated TestInfo namedtuple if suite_name matches
137            a suite in constants.SUITE_PLAN, else check if the file
138            existing in the suite plan dirs, else return None.
139        """
140        logging.debug('Finding test by suite: %s', suite_name)
141        if suite_name in constants.SUITE_PLANS:
142            return test_info.TestInfo(
143                test_name=suite_name,
144                test_runner=self._SUITE_PLAN_TEST_RUNNER,
145                build_targets=set([suite_name]),
146                suite=suite_name)
147        test_file = test_finder_utils.search_integration_dirs(
148            suite_name, self.suite_plan_dirs)
149        if test_file is None:
150            return None
151        return self._get_test_info_from_path(test_file, suite_name)
152