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""" 16TestInfo class. 17""" 18 19from collections import namedtuple 20 21# pylint: disable=import-error 22import constants 23 24 25TestFilterBase = namedtuple('TestFilter', ['class_name', 'methods']) 26 27 28class TestInfo(object): 29 """Information needed to identify and run a test.""" 30 31 # pylint: disable=too-many-arguments 32 def __init__(self, test_name, test_runner, build_targets, data=None, 33 suite=None, module_class=None, install_locations=None, 34 test_finder='', compatibility_suites=None): 35 """Init for TestInfo. 36 37 Args: 38 test_name: String of test name. 39 test_runner: String of test runner. 40 build_targets: Set of build targets. 41 data: Dict of data for test runners to use. 42 suite: Suite for test runners to use. 43 module_class: A list of test classes. It's a snippet of class 44 in module_info. e.g. ["EXECUTABLES", "NATIVE_TESTS"] 45 install_locations: Set of install locations. 46 e.g. set(['host', 'device']) 47 test_finder: String of test finder. 48 compatibility_suites: A list of compatibility_suites. It's a 49 snippet of compatibility_suites in module_info. e.g. 50 ["device-tests", "vts10"] 51 """ 52 self.test_name = test_name 53 self.test_runner = test_runner 54 self.build_targets = build_targets 55 self.data = data if data else {} 56 self.suite = suite 57 self.module_class = module_class if module_class else [] 58 self.install_locations = (install_locations if install_locations 59 else set()) 60 # True if the TestInfo is built from a test configured in TEST_MAPPING. 61 self.from_test_mapping = False 62 # True if the test should run on host and require no device. The 63 # attribute is only set through TEST_MAPPING file. 64 self.host = False 65 self.test_finder = test_finder 66 self.compatibility_suites = (map(str, compatibility_suites) 67 if compatibility_suites else []) 68 69 def __str__(self): 70 host_info = (' - runs on host without device required.' if self.host 71 else '') 72 return ('test_name: %s - test_runner:%s - build_targets:%s - data:%s - ' 73 'suite:%s - module_class: %s - install_locations:%s%s - ' 74 'test_finder: %s - compatibility_suites:%s' % ( 75 self.test_name, self.test_runner, self.build_targets, 76 self.data, self.suite, self.module_class, 77 self.install_locations, host_info, self.test_finder, 78 self.compatibility_suites)) 79 80 def get_supported_exec_mode(self): 81 """Get the supported execution mode of the test. 82 83 Determine the test supports which execution mode by strategy: 84 Robolectric/JAVA_LIBRARIES --> 'both' 85 Not native tests or installed only in out/target --> 'device' 86 Installed only in out/host --> 'both' 87 Installed under host and target --> 'both' 88 89 Return: 90 String of execution mode. 91 """ 92 install_path = self.install_locations 93 if not self.module_class: 94 return constants.DEVICE_TEST 95 # Let Robolectric test support both. 96 if constants.MODULE_CLASS_ROBOLECTRIC in self.module_class: 97 return constants.BOTH_TEST 98 # Let JAVA_LIBRARIES support both. 99 if constants.MODULE_CLASS_JAVA_LIBRARIES in self.module_class: 100 return constants.BOTH_TEST 101 if not install_path: 102 return constants.DEVICE_TEST 103 # Non-Native test runs on device-only. 104 if constants.MODULE_CLASS_NATIVE_TESTS not in self.module_class: 105 return constants.DEVICE_TEST 106 # Native test with install path as host should be treated as both. 107 # Otherwise, return device test. 108 if len(install_path) == 1 and constants.DEVICE_TEST in install_path: 109 return constants.DEVICE_TEST 110 return constants.BOTH_TEST 111 112 113class TestFilter(TestFilterBase): 114 """Information needed to filter a test in Tradefed""" 115 116 def to_set_of_tf_strings(self): 117 """Return TestFilter as set of strings in TradeFed filter format.""" 118 if self.methods: 119 return {'%s#%s' % (self.class_name, m) for m in self.methods} 120 return {self.class_name} 121