1# 2# Copyright (C) 2017 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17import json 18import logging 19 20from vts.runners.host import asserts 21from vts.runners.host import const 22 23VTS_TESTABILITY_CHECKER_32 = "/data/local/tmp/vts_testability_checker32" 24VTS_TESTABILITY_CHECKER_64 = "/data/local/tmp/vts_testability_checker64" 25 26 27def GetHalServiceName(shell, hal, bitness="64", run_as_compliance_test=False): 28 """Determine whether to run a VTS test against a HAL and get the service 29 names of the given hal if determine to run. 30 31 Args: 32 shell: the ShellMirrorObject to execute command on the device. 33 hal: string, the FQName of a HAL service, e.g., 34 android.hardware.foo@1.0::IFoo 35 bitness: string, the bitness of the test. 36 run_as_compliance_test: boolean, whether it is a compliance test. 37 38 Returns: 39 a boolean whether to run the test against the given hal. 40 a set containing all service names for the given HAL. 41 """ 42 43 binary = VTS_TESTABILITY_CHECKER_64 44 if bitness == "32": 45 binary = VTS_TESTABILITY_CHECKER_32 46 # Give permission to execute the binary. 47 shell.Execute("chmod 755 %s" % binary) 48 cmd = binary 49 if run_as_compliance_test: 50 cmd += " -c " 51 cmd += " -b " + bitness + " " + hal 52 cmd_results = shell.Execute(str(cmd)) 53 asserts.assertFalse( 54 any(cmd_results[const.EXIT_CODE]), 55 "Failed to run vts_testability_checker. ErrorCode: %s\n STDOUT: %s\n STDERR: %s\n" 56 % (cmd_results[const.EXIT_CODE][0], cmd_results[const.STDOUT][0], 57 cmd_results[const.STDERR][0])) 58 result = json.loads(cmd_results[const.STDOUT][0]) 59 if str(result['Testable']).lower() == "true": 60 return True, set(result['instances']) 61 else: 62 return False, () 63 64 65class CombMode(object): 66 """Enum for service name combination mode""" 67 FULL_PERMUTATION = 0 68 NAME_MATCH = 1 69 NO_COMBINATION = 2 70 71 72def GetServiceInstancesCombinations(services, 73 service_instances, 74 mode=CombMode.FULL_PERMUTATION): 75 """Create combinations of instances for all services. 76 77 Args: 78 services: list, all services used in the test. e.g. [s1, s2] 79 service_instances: dictionary, mapping of each service and the 80 corresponding service name(s). 81 e.g. {"s1": ["n1"], "s2": ["n2", "n3"]} 82 mode: CombMode that determines the combination strategy. 83 84 Returns: 85 A list of service instance combinations. 86 """ 87 if mode == CombMode.FULL_PERMUTATION: 88 return GetServiceInstancesFullCombinations(services, service_instances) 89 elif mode == CombMode.NAME_MATCH: 90 return GetServiceInstancesNameMatchCombinations( 91 services, service_instances) 92 else: 93 logging.warning("Unknown comb mode, use default comb mode instead.") 94 return GetServiceInstancesFullCombinations(services, service_instances) 95 96 97def GetServiceInstancesFullCombinations(services, service_instances): 98 """Create all combinations of instances for all services. 99 100 Create full permutation for registered service instances, e.g. 101 s1 have instances (n1, n2) and s2 have instances (n3, n4), return all 102 permutations of s1 and s2, i.e. (s1/n1, s2/n3), (s1/n1, s2/n4), 103 (s1/n2, s2/n3) and (s1/n2, s2/n4) 104 105 Args: 106 services: list, all services used in the test. e.g. [s1, s2] 107 service_instances: dictionary, mapping of each service and the 108 corresponding service name(s). 109 e.g. {"s1": ["n1"], "s2": ["n2", "n3"]} 110 111 Returns: 112 A list of all service instance combinations. 113 e.g. [[s1/n1, s2/n2], [s1/n1, s2/n3]] 114 """ 115 service_instance_combinations = [] 116 if not services or (service_instances and type(service_instances) != dict): 117 return service_instance_combinations 118 service = services.pop() 119 pre_instance_combs = GetServiceInstancesCombinations( 120 services, service_instances) 121 if service not in service_instances or not service_instances[service]: 122 return pre_instance_combs 123 for name in service_instances[service]: 124 if not pre_instance_combs: 125 new_instance_comb = [service + '/' + name] 126 service_instance_combinations.append(new_instance_comb) 127 else: 128 for instance_comb in pre_instance_combs: 129 new_instance_comb = [service + '/' + name] 130 new_instance_comb.extend(instance_comb) 131 service_instance_combinations.append(new_instance_comb) 132 133 return service_instance_combinations 134 135 136def GetServiceInstancesNameMatchCombinations(services, service_instances): 137 """Create service instance combinations with same name for services. 138 139 Create combinations for services with the same instance name, e.g. 140 both s1 and s2 have two instances with name n1, and n2, return 141 the service instance combination of s1 and s2 with same instance name, 142 i.e. (s1/n1, s2/n1) and (s1/n2, s2/n2) 143 144 Args: 145 services: list, all services used in the test. e.g. [s1, s2] 146 service_instances: dictionary, mapping of each service and the 147 corresponding service name(s). 148 e.g. {"s1": ["n1", "n2"], "s2": ["n1", "n2"]} 149 150 Returns: 151 A list of service instance combinations. 152 e.g. [[s1/n1, s2/n1], [s1/n2, s2/n2]] 153 """ 154 service_instance_combinations = [] 155 instance_names = set() 156 for service in services: 157 if service not in service_instances or not service_instances[service]: 158 logging.error("Does not found instance for service: %s", service) 159 return [] 160 if not instance_names: 161 instance_names = set(service_instances[service]) 162 else: 163 instance_names.intersection_update(set(service_instances[service])) 164 165 for name in instance_names: 166 instance_comb = [] 167 for service in services: 168 new_instance = [service + '/' + name] 169 instance_comb.extend(new_instance) 170 service_instance_combinations.append(instance_comb) 171 172 return service_instance_combinations 173