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